Android自定义View实现刮刮乐效果

看到支付宝的刮刮乐效果,一直在想着自己实现一下这个效果,也查找了挺多的资料,晚上自己粗略的实现了,先上效果图:

初始图片
刮开图片

现在来谈谈实现思路,这里是使用了图层的思路来实现,首先自己定制一个用来当做覆盖用的图层,颜色为灰色。接着在View onDraw的时候先绘制被覆盖的内容图层,然后绘制自己定制的用来当做覆盖用的图层,初始化的效果就是图片1。刮开的效果是重写了View的onTouchEvent方法,监听用户的滑动事件,在用来当做覆盖用的图层上用透明度为0的画笔绘制路径,这样在这个图层上滑动的轨迹颜色变为透明,就会显示下层的内容图层。这里涉及到的知识还有Android中的xfermode,这里不详细赘述,有兴趣的可以网上搜索。

自定义的View代码如下:

/**
 * Created by MarRn on 2016/6/29.
 */
public class ScrapeView extends View{

    //被覆盖的内容图层
    private Bitmap bpBackground;
    //用来当做覆盖用的图层
    private Bitmap bpForeground;
    //用来当做覆盖用的图层的画布
    private Canvas mCanvas;
    //模拟手指头刮开路径的画笔
    private Paint pathPaint;
    //手指头刮开的路径
    private Path path;

    //用来当做覆盖用的图层的文字画笔
    private Paint contentPaint;
    //用来当做覆盖用的图层的文字内容
    private String content = "刮刮看咯~";

    public ScrapeView(Context context) {
        super(context);
        init();
    }

    public ScrapeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init(){

        //初始化模拟刮开路径的画笔
        pathPaint = new Paint();
        pathPaint.setAlpha(0);
        pathPaint.setStyle(Paint.Style.STROKE);
        pathPaint.setStrokeWidth(50);
        //取两层绘制交集,显示下层
        pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));
        pathPaint.setStrokeJoin(Paint.Join.ROUND);
        pathPaint.setStrokeCap(Paint.Cap.ROUND);


        //初始化模拟手指头刮开的路径
        path = new Path();


        //初始化被覆盖的内容bitmap
        bpBackground = BitmapFactory.decodeResource(getResources(),R.drawable.test);
        //初始化用来当做覆盖用的bitmap
        bpForeground = Bitmap.createBitmap(bpBackground.getWidth(),bpBackground.getHeight(), Bitmap.Config.ARGB_8888);

        //初始化画布
        mCanvas = new Canvas(bpForeground);

        //初始化内容画笔
        contentPaint = new Paint();
        contentPaint.setColor(Color.WHITE);
        contentPaint.setTextSize(100);
        contentPaint.setStrokeWidth(20);

        //设置用来当做覆盖用的图层颜色为灰色
        mCanvas.drawColor(Color.GRAY);
        //在用来当做覆盖用的图层上绘制文字
        mCanvas.drawText(content,mCanvas.getWidth()/4,mCanvas.getHeight()/2,contentPaint);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //清空画笔
                path.reset();
                //原点移动至手指的触摸点
                path.moveTo(event.getX(),event.getY());
                break;
            case MotionEvent.ACTION_MOVE:

                path.lineTo(event.getX(),event.getY());
                break;
        }

        //模拟刮来效果
        mCanvas.drawPath(path,pathPaint);
        invalidate();
        return true;

    }

    @Override
    protected void onDraw(Canvas canvas) {

        //绘制两个图层
        canvas.drawBitmap(bpBackground,0,0,null);
        canvas.drawBitmap(bpForeground,0,0,null);

    }
}

xml文件中的使用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <com.marrn.test.ScrapeView

        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

这是这几天研究View的自定义,事件机制和2D绘图的结合,有哪里不妥的地方请指教~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值