安卓下的刮刮卡摸奖的实现
indam
8年前
<p>效果如下:</p> <p><img src="https://simg.open-open.com/show/396f88d771772cdf08313ae1cb0123b2.jpg"></p> <p>呱呱卡开奖前</p> <p><img src="https://simg.open-open.com/show/de89932c6bb1c3165892e71d1ea40888.jpg"></p> <p>呱呱卡开奖后</p> <h3>实现思路</h3> <p>一张呱呱卡有三层,最底层我用一个TextView控件显示中奖内容,中间层是刮完之后的显示图样,最上面一层是刮刮卡的封面。手指刮除封面的过程就是把刮刮卡最上面一层裁剪的过程。</p> <h3>涉及的知识点</h3> <ol> <li>canvas.clipPath(),Path类,Region.Op类</li> <li>onDraw方法和onTouchEvent方法的配合</li> </ol> <p>核心代码如下:</p> <pre> <code class="language-java">public class LotteryView extends View { public static final int STROKE_WIDTH = 15; private float mEventX; private float mEventY; /** * 呱呱卡封面 画笔 */ private Paint mOverlayPaint; private RectF mRectBorder; /** * 呱呱卡边缘 画笔 */ private Paint mStrokePaint; private RectF mRectFill; private Path mClipPath; public LotteryView(Context context) { this(context,null,0); } public LotteryView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LotteryView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { Bitmap lotteryOverlay = BitmapFactory.decodeResource(getResources(), R.drawable.icon_lottery_overlay); mOverlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mOverlayPaint.setShader(new BitmapShader(lotteryOverlay, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)); mStrokePaint = new Paint(); mStrokePaint.setAntiAlias(true); mStrokePaint.setStyle(Paint.Style.STROKE); mStrokePaint.setColor(Color.BLACK); mStrokePaint.setStrokeWidth(STROKE_WIDTH); mClipPath = new Path(); } @Override protected void onDraw(Canvas canvas) { if (mRectBorder == null) { mRectBorder = new RectF(0, 0, getWidth(), getHeight()); } if (mRectFill == null) { mRectFill = new RectF(0, 0, getWidth(), getHeight()); } canvas.drawRoundRect(mRectBorder, 10, 10, mStrokePaint); if (mEventX != 0 || mEventY != 0) { mClipPath.addCircle(mEventX, mEventY, 50, Path.Direction.CW); canvas.clipPath(mClipPath, Region.Op.DIFFERENCE); } canvas.drawRect(mRectFill, mOverlayPaint); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_MOVE: mEventX = event.getX(); mEventY = event.getY(); invalidate(); break; } return true; } }</code></pre> <p>布局里的使用</p> <pre> <code class="language-xml"><RelativeLayout android:layout_width="match_parent" android:layout_height="120dp" > <TextView android:id="@+id/tv_lottery_content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:gravity="center" android:textColor="@android:color/white" android:textSize="20sp" android:background="@android:color/darker_gray" android:text="恭喜您,荣获2016年年度最佳程序员" /> <com.sugary.roundimageview.LotteryView android:layout_width="match_parent" android:layout_height="120dp" /> </RelativeLayout></code></pre> <h3>小结</h3> <ol> <li>刮刮卡的中奖内容是放在TextView控件,作为最底层显示。</li> <li>如果项目里需要有刮卡完成后回调,可以计算刮除的面积与刮刮卡总面积的比例,超过一定值,即认为呱卡完成。</li> <li>后续的优化方向可以是,把底层的TextView放到LotteryView自定义控件里</li> </ol> <p> </p> <p>来自:http://www.jianshu.com/p/2f17658eed60</p> <p> </p>