├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── snapshot1.jpeg ├── snapshot2.jpeg └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── laxian │ │ └── guideview │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── laxian │ │ │ └── guideview │ │ │ ├── GuideView.java │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-xhdpi │ │ └── img_new_task_guide.png │ │ ├── drawable │ │ └── ic_menu_moreoverflow.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── app_bar.xml │ │ └── content_main.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── laxian │ └── guideview │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── 11.jpg ├── a.png └── b.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | /.idea 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GuideView 2 | 新手引导视图,初次打开页面时显示。 3 | 支持圆形,椭圆,矩形等多种图形 4 | 提示部分支持图片和文字提示 5 | 6 | #先看效果图 7 | ![image](https://github.com/qiushi123/GuideView-master/blob/master/images/11.jpg?raw=true) 8 | 9 | 10 | 11 | #使用步骤。 12 | ###使用起来特别简单,只需要把GuideView这个类复制到你的项目中就可以了 13 | 14 | 15 | *使用图片 16 | 17 | ImageView iv = new ImageView(this); 18 | iv.setImageResource(R.drawable.img_new_task_guide); 19 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( 20 | ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 21 | iv.setLayoutParams(params); 22 | 23 | ![image](https://github.com/qiushi123/GuideView-master/blob/master/images/a.png?raw=true) 24 | 25 | *使用文字 26 | 27 | TextView iv = new TextView(this); 28 | iv.setText("欢迎使用"); 29 | iv.setTextColor(getResources().getColor(R.color.white)); 30 | 31 | ![image](https://github.com/qiushi123/GuideView-master/blob/master/images/b.png?raw=true) 32 | 33 | *显示GuideView 34 | 35 | GuideView.Builder 36 | .newInstance(this) // 必须调用 37 | .setTargetView(view) // 必须调用,设置需要Guide的View 38 | .setCustomTipsView(iv) // 必须调用,设置GuideView,可以使任意View的实例,比如ImageView 或者TextView 39 | .setDirction(GuideView.Direction.LEFT_BOTTOM) // 设置GuideView 相对于TargetView的位置,有八种,不设置则默认在屏幕左上角,其余的可以显示在右上,右下等等 40 | .setShape(GuideView.MyShape.RECTANGULAR) // 设置显示形状,支持圆形,椭圆,矩形三种样式,矩形可以是圆角矩形, 41 | .setBackGround(getResources().getColor(R.color.shadow)) // 设置背景颜色,默认透明 42 | .setOnclickExit(null) // 设置点击消失,可以传入一个Callback,执行被点击后的操作 43 | .setRadius(32) // 设置圆形或矩形透明区域半径,默认是targetView的显示矩形的半径,如果是矩形,这里是设置矩形圆角大小 44 | .setCenter(300, 300) // 设置圆心,默认是targetView的中心 45 | .setOffset(200, 60) // 设置偏移,一般用于微调GuideView的位置 46 | .showOnce() // 设置首次显示,设置后,显示一次后,不再显示 47 | .build() // 必须调用,Buider模式,返回GuideView实例 48 | .show(); // 必须调用,显示GuideView 49 | 50 | 51 | ##博客详解地址: 52 | http://blog.csdn.net/qiushi_1990/article/details/51558319 53 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '23.0.2' 6 | defaultConfig { 7 | applicationId "com.laxian.guideview" 8 | minSdkVersion 16 9 | targetSdkVersion 19 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | productFlavors { 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(include: ['*.jar'], dir: 'libs') 25 | testCompile 'junit:junit:4.12' 26 | compile 'com.android.support:appcompat-v7:23.+' 27 | compile 'com.android.support:design:23.+' 28 | } 29 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/snapshot1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiushi123/GuideView-master/66d511f2ef0d07ea0c86db3f7f6e6bd285618299/app/snapshot1.jpeg -------------------------------------------------------------------------------- /app/snapshot2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiushi123/GuideView-master/66d511f2ef0d07ea0c86db3f7f6e6bd285618299/app/snapshot2.jpeg -------------------------------------------------------------------------------- /app/src/androidTest/java/com/laxian/guideview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.laxian.guideview; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/laxian/guideview/GuideView.java: -------------------------------------------------------------------------------- 1 | package com.laxian.guideview; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.PorterDuffXfermode; 10 | import android.graphics.RectF; 11 | import android.util.Log; 12 | import android.view.Gravity; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.view.ViewTreeObserver; 16 | import android.widget.FrameLayout; 17 | import android.widget.RelativeLayout; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * Created by zhouweixian on 2016/1/23. 23 | */ 24 | public class GuideView extends RelativeLayout implements ViewTreeObserver.OnGlobalLayoutListener { 25 | private final String TAG = getClass().getSimpleName(); 26 | private Context mContent; 27 | private List mViews; 28 | private boolean first = true; 29 | /** 30 | * targetView前缀。SHOW_GUIDE_PREFIX + targetView.getId()作为保存在SP文件的key。 31 | */ 32 | private static final String SHOW_GUIDE_PREFIX = "show_guide_on_view_"; 33 | /** 34 | * GuideView 偏移量 35 | */ 36 | private int offsetX, offsetY; 37 | /** 38 | * targetView 的外切圆半径 39 | */ 40 | private int radius; 41 | /** 42 | * 需要显示提示信息的View 43 | */ 44 | private View targetView; 45 | /** 46 | * 自定义View 47 | */ 48 | private View customGuideView; 49 | /** 50 | * 透明圆形画笔 51 | */ 52 | private Paint mCirclePaint; 53 | /** 54 | * 背景色画笔 55 | */ 56 | private Paint mBackgroundPaint; 57 | /** 58 | * targetView是否已测量 59 | */ 60 | private boolean isMeasured; 61 | /** 62 | * targetView圆心 63 | */ 64 | private int[] center; 65 | /** 66 | * 绘图层叠模式 67 | */ 68 | private PorterDuffXfermode porterDuffXfermode; 69 | /** 70 | * 绘制前景bitmap 71 | */ 72 | private Bitmap bitmap; 73 | /** 74 | * 背景色和透明度,格式 #aarrggbb 75 | */ 76 | private int backgroundColor; 77 | /** 78 | * Canvas,绘制bitmap 79 | */ 80 | private Canvas temp; 81 | /** 82 | * 相对于targetView的位置.在target的那个方向 83 | */ 84 | private Direction direction; 85 | 86 | /** 87 | * 形状 88 | */ 89 | private MyShape myShape; 90 | /** 91 | * targetView左上角坐标 92 | */ 93 | private int[] location; 94 | private boolean onClickExit; 95 | private OnClickCallback onclickListener; 96 | private RelativeLayout guideViewLayout; 97 | 98 | public void restoreState() { 99 | Log.v(TAG, "restoreState"); 100 | offsetX = offsetY = 0; 101 | radius = 0; 102 | mCirclePaint = null; 103 | mBackgroundPaint = null; 104 | isMeasured = false; 105 | center = null; 106 | porterDuffXfermode = null; 107 | bitmap = null; 108 | needDraw = true; 109 | // backgroundColor = Color.parseColor("#00000000"); 110 | temp = null; 111 | // direction = null; 112 | 113 | } 114 | 115 | public int[] getLocation() { 116 | return location; 117 | } 118 | 119 | public void setLocation(int[] location) { 120 | this.location = location; 121 | } 122 | 123 | public GuideView(Context context) { 124 | super(context); 125 | this.mContent = context; 126 | init(); 127 | } 128 | 129 | public int getRadius() { 130 | return radius; 131 | } 132 | 133 | public void setRadius(int radius) { 134 | this.radius = radius; 135 | } 136 | 137 | public void setOffsetX(int offsetX) { 138 | this.offsetX = offsetX; 139 | } 140 | 141 | public void setOffsetY(int offsetY) { 142 | this.offsetY = offsetY; 143 | } 144 | 145 | public void setDirection(Direction direction) { 146 | this.direction = direction; 147 | } 148 | 149 | public void setShape(MyShape shape) { 150 | this.myShape = shape; 151 | } 152 | 153 | public void setCustomGuideView(View customGuideView) { 154 | this.customGuideView = customGuideView; 155 | if (!first) { 156 | restoreState(); 157 | } 158 | } 159 | 160 | public void setBgColor(int background_color) { 161 | this.backgroundColor = background_color; 162 | } 163 | 164 | public View getTargetView() { 165 | return targetView; 166 | } 167 | 168 | public void setTargetView(View targetView) { 169 | this.targetView = targetView; 170 | // restoreState(); 171 | if (!first) { 172 | // guideViewLayout.removeAllViews(); 173 | } 174 | } 175 | 176 | private void init() { 177 | } 178 | 179 | public void showOnce() { 180 | if (targetView != null) { 181 | mContent.getSharedPreferences(TAG, Context.MODE_PRIVATE).edit().putBoolean(generateUniqId(targetView), true).commit(); 182 | } 183 | } 184 | 185 | private boolean hasShown() { 186 | if (targetView == null) 187 | return true; 188 | return mContent.getSharedPreferences(TAG, Context.MODE_PRIVATE).getBoolean(generateUniqId(targetView), false); 189 | } 190 | 191 | private String generateUniqId(View v) { 192 | return SHOW_GUIDE_PREFIX + v.getId(); 193 | } 194 | 195 | public int[] getCenter() { 196 | return center; 197 | } 198 | 199 | public void setCenter(int[] center) { 200 | this.center = center; 201 | } 202 | 203 | public void hide() { 204 | Log.v(TAG, "hide"); 205 | if (customGuideView != null) { 206 | targetView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 207 | this.removeAllViews(); 208 | ((FrameLayout) ((Activity) mContent).getWindow().getDecorView()).removeView(this); 209 | restoreState(); 210 | } 211 | } 212 | 213 | public void show() { 214 | Log.v(TAG, "show"); 215 | if (hasShown()) 216 | return; 217 | 218 | if (targetView != null) { 219 | targetView.getViewTreeObserver().addOnGlobalLayoutListener(this); 220 | } 221 | 222 | this.setBackgroundResource(R.color.transparent); 223 | 224 | ((FrameLayout) ((Activity) mContent).getWindow().getDecorView()).addView(this); 225 | first = false; 226 | } 227 | 228 | /** 229 | * 添加提示文字,位置在targetView的下边 230 | * 在屏幕窗口,添加蒙层,蒙层绘制总背景和透明圆形,圆形下边绘制说明文字 231 | */ 232 | private void createGuideView() { 233 | Log.v(TAG, "createGuideView"); 234 | 235 | // 添加到蒙层 236 | // if (guideViewLayout == null) { 237 | // guideViewLayout = new RelativeLayout(mContent); 238 | // } 239 | 240 | // Tips布局参数 241 | LayoutParams guideViewParams; 242 | guideViewParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 243 | guideViewParams.setMargins(0, center[1] + radius + 10, 0, 0); 244 | 245 | if (customGuideView != null) { 246 | 247 | // LayoutParams guideViewParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 248 | if (direction != null) { 249 | int width = this.getWidth(); 250 | int height = this.getHeight(); 251 | 252 | int left = center[0] - radius; 253 | int right = center[0] + radius; 254 | int top = center[1] - radius; 255 | int bottom = center[1] + radius; 256 | switch (direction) { 257 | case TOP: 258 | this.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); 259 | guideViewParams.setMargins(offsetX, offsetY - height + top, -offsetX, height - top - offsetY); 260 | break; 261 | case LEFT: 262 | this.setGravity(Gravity.RIGHT); 263 | guideViewParams.setMargins(offsetX - width + left, top + offsetY, width - left - offsetX, -top - offsetY); 264 | break; 265 | case BOTTOM: 266 | this.setGravity(Gravity.CENTER_HORIZONTAL); 267 | guideViewParams.setMargins(offsetX, bottom + offsetY, -offsetX, -bottom - offsetY); 268 | break; 269 | case RIGHT: 270 | guideViewParams.setMargins(right + offsetX, top + offsetY, -right - offsetX, -top - offsetY); 271 | break; 272 | case LEFT_TOP: 273 | this.setGravity(Gravity.RIGHT | Gravity.BOTTOM); 274 | guideViewParams.setMargins(offsetX - width + left, offsetY - height + top, width - left - offsetX, height - top - offsetY); 275 | break; 276 | case LEFT_BOTTOM: 277 | this.setGravity(Gravity.RIGHT); 278 | guideViewParams.setMargins(offsetX - width + left, bottom + offsetY, width - left - offsetX, -bottom - offsetY); 279 | break; 280 | case RIGHT_TOP: 281 | this.setGravity(Gravity.BOTTOM); 282 | guideViewParams.setMargins(right + offsetX, offsetY - height + top, -right - offsetX, height - top - offsetY); 283 | break; 284 | case RIGHT_BOTTOM: 285 | guideViewParams.setMargins(right + offsetX, bottom + offsetY, -right - offsetX, -top - offsetY); 286 | break; 287 | } 288 | } else { 289 | guideViewParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 290 | guideViewParams.setMargins(offsetX, offsetY, -offsetX, -offsetY); 291 | } 292 | 293 | // guideViewLayout.addView(customGuideView); 294 | 295 | this.addView(customGuideView, guideViewParams); 296 | } 297 | } 298 | 299 | /** 300 | * 获得targetView 的宽高,如果未测量,返回{-1, -1} 301 | * 302 | * @return 303 | */ 304 | private int[] getTargetViewSize() { 305 | int[] location = {-1, -1}; 306 | if (isMeasured) { 307 | location[0] = targetView.getWidth(); 308 | location[1] = targetView.getHeight(); 309 | } 310 | return location; 311 | } 312 | 313 | /** 314 | * 获得targetView 的半径 315 | * 316 | * @return 317 | */ 318 | private int getTargetViewRadius() { 319 | if (isMeasured) { 320 | int[] size = getTargetViewSize(); 321 | int x = size[0]; 322 | int y = size[1]; 323 | 324 | return (int) (Math.sqrt(x * x + y * y) / 2); 325 | } 326 | return -1; 327 | } 328 | 329 | boolean needDraw = true; 330 | 331 | @Override 332 | protected void onDraw(Canvas canvas) { 333 | super.onDraw(canvas); 334 | Log.v(TAG, "onDraw"); 335 | 336 | if (!isMeasured) 337 | return; 338 | 339 | if (targetView == null) 340 | return; 341 | 342 | // if (!needDraw) return; 343 | 344 | drawBackground(canvas); 345 | 346 | } 347 | 348 | private void drawBackground(Canvas canvas) { 349 | Log.v(TAG, "drawBackground"); 350 | needDraw = false; 351 | // 先绘制bitmap,再将bitmap绘制到屏幕 352 | bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); 353 | temp = new Canvas(bitmap); 354 | 355 | // 背景画笔 356 | Paint bgPaint = new Paint(); 357 | if (backgroundColor != 0) 358 | bgPaint.setColor(backgroundColor); 359 | else 360 | bgPaint.setColor(getResources().getColor(R.color.shadow)); 361 | 362 | // 绘制屏幕背景 363 | temp.drawRect(0, 0, temp.getWidth(), temp.getHeight(), bgPaint); 364 | 365 | // targetView 的透明圆形画笔 366 | if (mCirclePaint == null) 367 | mCirclePaint = new Paint(); 368 | porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT);// 或者CLEAR 369 | mCirclePaint.setXfermode(porterDuffXfermode); 370 | mCirclePaint.setAntiAlias(true); 371 | 372 | if (myShape != null) { 373 | RectF oval = new RectF(); 374 | switch (myShape) { 375 | case CIRCULAR://圆形 376 | temp.drawCircle(center[0], center[1], radius, mCirclePaint);//绘制圆形 377 | break; 378 | case ELLIPSE://椭圆 379 | //RectF对象 380 | oval.left = center[0] - 150; //左边 381 | oval.top = center[1] - 50; //上边 382 | oval.right = center[0] + 150; //右边 383 | oval.bottom = center[1] + 50; //下边 384 | temp.drawOval(oval, mCirclePaint); //绘制椭圆 385 | break; 386 | case RECTANGULAR://圆角矩形 387 | //RectF对象 388 | oval.left = center[0] - 150; //左边 389 | oval.top = center[1] - 50; //上边 390 | oval.right = center[0] + 150; //右边 391 | oval.bottom = center[1] + 50; //下边 392 | temp.drawRoundRect(oval, radius, radius, mCirclePaint); //绘制圆角矩形 393 | break; 394 | } 395 | } else { 396 | temp.drawCircle(center[0], center[1], radius, mCirclePaint);//绘制圆形 397 | } 398 | 399 | // 绘制到屏幕 400 | canvas.drawBitmap(bitmap, 0, 0, bgPaint); 401 | bitmap.recycle(); 402 | } 403 | 404 | public void setOnClickExit(boolean onClickExit) { 405 | this.onClickExit = onClickExit; 406 | } 407 | 408 | public void setOnclickListener(OnClickCallback onclickListener) { 409 | this.onclickListener = onclickListener; 410 | } 411 | 412 | private void setClickInfo() { 413 | final boolean exit = onClickExit; 414 | setOnClickListener(new OnClickListener() { 415 | @Override 416 | public void onClick(View v) { 417 | if (onclickListener != null) { 418 | onclickListener.onClickedGuideView(); 419 | } 420 | if (exit) { 421 | hide(); 422 | } 423 | } 424 | }); 425 | } 426 | 427 | @Override 428 | public void onGlobalLayout() { 429 | if (isMeasured) 430 | return; 431 | if (targetView.getHeight() > 0 && targetView.getWidth() > 0) { 432 | isMeasured = true; 433 | } 434 | 435 | // 获取targetView的中心坐标 436 | if (center == null) { 437 | // 获取右上角坐标 438 | location = new int[2]; 439 | targetView.getLocationInWindow(location); 440 | center = new int[2]; 441 | // 获取中心坐标 442 | center[0] = location[0] + targetView.getWidth() / 2; 443 | center[1] = location[1] + targetView.getHeight() / 2; 444 | } 445 | // 获取targetView外切圆半径 446 | if (radius == 0) { 447 | radius = getTargetViewRadius(); 448 | } 449 | // 添加GuideView 450 | createGuideView(); 451 | } 452 | 453 | /** 454 | * 定义GuideView相对于targetView的方位,共八种。不设置则默认在targetView下方 455 | */ 456 | enum Direction { 457 | LEFT, TOP, RIGHT, BOTTOM, 458 | LEFT_TOP, LEFT_BOTTOM, 459 | RIGHT_TOP, RIGHT_BOTTOM 460 | } 461 | 462 | /** 463 | * 定义目标控件的形状,共3种。圆形,椭圆,带圆角的矩形(可以设置圆角大小),不设置则默认是圆形 464 | */ 465 | enum MyShape { 466 | CIRCULAR, ELLIPSE, RECTANGULAR 467 | } 468 | 469 | /** 470 | * GuideView点击Callback 471 | */ 472 | interface OnClickCallback { 473 | void onClickedGuideView(); 474 | } 475 | 476 | public static class Builder { 477 | static GuideView guiderView; 478 | static Builder instance = new Builder(); 479 | Context mContext; 480 | 481 | private Builder() { 482 | } 483 | 484 | public Builder(Context ctx) { 485 | mContext = ctx; 486 | } 487 | 488 | public static Builder newInstance(Context ctx) { 489 | guiderView = new GuideView(ctx); 490 | return instance; 491 | } 492 | 493 | public Builder setTargetView(View target) { 494 | guiderView.setTargetView(target); 495 | return instance; 496 | } 497 | 498 | public Builder setBgColor(int color) { 499 | guiderView.setBgColor(color); 500 | return instance; 501 | } 502 | 503 | public Builder setDirction(Direction dir) { 504 | guiderView.setDirection(dir); 505 | return instance; 506 | } 507 | 508 | public Builder setShape(MyShape shape) { 509 | guiderView.setShape(shape); 510 | return instance; 511 | } 512 | 513 | public Builder setOffset(int x, int y) { 514 | guiderView.setOffsetX(x); 515 | guiderView.setOffsetY(y); 516 | return instance; 517 | } 518 | 519 | public Builder setRadius(int radius) { 520 | guiderView.setRadius(radius); 521 | return instance; 522 | } 523 | 524 | public Builder setCustomGuideView(View view) { 525 | guiderView.setCustomGuideView(view); 526 | return instance; 527 | } 528 | 529 | public Builder setCenter(int X, int Y) { 530 | guiderView.setCenter(new int[]{X, Y}); 531 | return instance; 532 | } 533 | 534 | public Builder showOnce() { 535 | guiderView.showOnce(); 536 | return instance; 537 | } 538 | 539 | public GuideView build() { 540 | guiderView.setClickInfo(); 541 | return guiderView; 542 | } 543 | 544 | public Builder setOnclickExit(boolean onclickExit) { 545 | guiderView.setOnClickExit(onclickExit); 546 | return instance; 547 | } 548 | 549 | public Builder setOnclickListener(final OnClickCallback callback) { 550 | guiderView.setOnclickListener(callback); 551 | return instance; 552 | } 553 | } 554 | } 555 | -------------------------------------------------------------------------------- /app/src/main/java/com/laxian/guideview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.laxian.guideview; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.Gravity; 6 | import android.view.ViewGroup; 7 | import android.widget.Button; 8 | import android.widget.ImageButton; 9 | import android.widget.ImageView; 10 | import android.widget.RelativeLayout; 11 | import android.widget.TextView; 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | private ImageButton menu; 16 | private Button btnTest; 17 | private Button btnTest2; 18 | private GuideView guideView; 19 | private GuideView guideView3; 20 | private GuideView guideView2; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_main); 26 | 27 | menu = (ImageButton) findViewById(R.id.ib_menu); 28 | btnTest = (Button) findViewById(R.id.btn_test); 29 | btnTest2 = (Button) findViewById(R.id.btn_test2); 30 | 31 | } 32 | 33 | private void setGuideView() { 34 | 35 | // 使用图片 36 | final ImageView iv = new ImageView(this); 37 | iv.setImageResource(R.drawable.img_new_task_guide); 38 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 39 | iv.setLayoutParams(params); 40 | 41 | // 使用文字 42 | TextView tv = new TextView(this); 43 | tv.setText("欢迎使用"); 44 | tv.setTextColor(getResources().getColor(R.color.white)); 45 | tv.setTextSize(30); 46 | tv.setGravity(Gravity.CENTER); 47 | 48 | // 使用文字 49 | final TextView tv2 = new TextView(this); 50 | tv2.setText("欢迎使用2"); 51 | tv2.setTextColor(getResources().getColor(R.color.white)); 52 | tv2.setTextSize(30); 53 | tv2.setGravity(Gravity.CENTER); 54 | 55 | 56 | guideView = GuideView.Builder 57 | .newInstance(this) 58 | .setTargetView(menu)//设置目标 59 | .setCustomGuideView(iv) 60 | .setDirction(GuideView.Direction.LEFT_BOTTOM) 61 | .setShape(GuideView.MyShape.CIRCULAR) // 设置圆形显示区域, 62 | .setBgColor(getResources().getColor(R.color.shadow)) 63 | .setOnclickListener(new GuideView.OnClickCallback() { 64 | @Override 65 | public void onClickedGuideView() { 66 | guideView.hide(); 67 | guideView2.show(); 68 | } 69 | }) 70 | .build(); 71 | 72 | 73 | guideView2 = GuideView.Builder 74 | .newInstance(this) 75 | .setTargetView(btnTest) 76 | .setCustomGuideView(tv) 77 | .setDirction(GuideView.Direction.LEFT_BOTTOM) 78 | .setShape(GuideView.MyShape.ELLIPSE) // 设置椭圆形显示区域, 79 | .setBgColor(getResources().getColor(R.color.shadow)) 80 | .setOnclickListener(new GuideView.OnClickCallback() { 81 | @Override 82 | public void onClickedGuideView() { 83 | guideView2.hide(); 84 | guideView3.show(); 85 | } 86 | }) 87 | .build(); 88 | 89 | 90 | guideView3 = GuideView.Builder 91 | .newInstance(this) 92 | .setTargetView(btnTest2) 93 | .setCustomGuideView(tv2) 94 | .setDirction(GuideView.Direction.LEFT_BOTTOM) 95 | .setShape(GuideView.MyShape.RECTANGULAR) // 设置矩形显示区域, 96 | .setRadius(80) // 设置圆形或矩形透明区域半径,默认是targetView的显示矩形的半径,如果是矩形,这里是设置矩形圆角大小 97 | .setBgColor(getResources().getColor(R.color.shadow)) 98 | .setOnclickListener(new GuideView.OnClickCallback() { 99 | @Override 100 | public void onClickedGuideView() { 101 | guideView3.hide(); 102 | guideView.show(); 103 | } 104 | }) 105 | .build(); 106 | 107 | guideView.show(); 108 | } 109 | 110 | @Override 111 | protected void onResume() { 112 | super.onResume(); 113 | setGuideView(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_new_task_guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiushi123/GuideView-master/66d511f2ef0d07ea0c86db3f7f6e6bd285618299/app/src/main/res/drawable-xhdpi/img_new_task_guide.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_moreoverflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiushi123/GuideView-master/66d511f2ef0d07ea0c86db3f7f6e6bd285618299/app/src/main/res/drawable/ic_menu_moreoverflow.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 27 | 28 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 |