iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android通过自定义view实现刮刮乐效果详解
  • 708
分享到

Android通过自定义view实现刮刮乐效果详解

2024-04-02 19:04:59 708人浏览 独家记忆
摘要

目录前言实现原理关键步骤创建bitmap绘制文字画路径完整代码前言 已经有两个月没有更新博客了,其实这篇文章我早在两个月前就写好了,一直保存在草稿箱里没有发布出来。原因是有一些原理性

前言

已经有两个月没有更新博客了,其实这篇文章我早在两个月前就写好了,一直保存在草稿箱里没有发布出来。原因是有一些原理性的东西还没了解清楚,最近抽时间研究了一下混合模式,终于也理解了刮刮乐是怎么实现的,所以想继续分享一下自己的一些心得,先上效果图。

效果图:

实现原理

其实刮刮乐实现原理也不算很复杂,最关键的还是需要了解Paint的混合模式。因为刮刮乐是由两个bitmap组成的,一个是源图另一个是目标图,我们需要把目标图的颜色改成灰色,在源图上面盖上了一张灰色的目标图。当手指滑动屏幕时paint会在新的canvas上画出路径,由于新的canvas会持有一个新的bitmap,最终两个bitmap的像素点重叠时就显示源图的部分,从而实现了刮刮乐的效果。这里用的是混合模式中的PorterDuff.Mode.DST_IN。

关键代码:

pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));

关键步骤

创建bitmap

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmapBackground = getBitmap(mBitmapBackground, w, h);
        mBitmapFront = Bitmap.createBitmap(mBitmapBackground.getWidth(),
                mBitmapBackground.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmapFront);
        drawText(mCanvas, w, h);
    }

onSizeChanged方法里面创建了两个bitmap,一个是背景图,另一个是覆盖在背景图上面的bitmap。然后是在上面的bitmap上面绘制文字。

绘制文字

    private void drawText(Canvas canvas, int mWidth, int mHeight) {
        String text = "赶紧刮开吧";
        canvas.drawColor(Color.GRAY);
        Paint.FontMetrics fm = mPaintText.getFontMetrics();
        int mTxtWidth = (int) mPaintText.measureText(text, 0, text.length());
        int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
        int x = mWidth / 2 - mTxtWidth / 2; //文字在画布中的x坐标
        int y = mHeight / 2 + mTxtHeight / 4; //文字在画布中的y坐标
        canvas.drawText(text, x, y, mPaintText);
    }

调用canvas的drawText方法绘制文字,x,y是文字中心位置的坐标。测量文字宽高有两种方式,这里用的是更精确的getFontMetrics方法。

画路径

    @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;
    }

最终效果图

完整代码

import Android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
 
import androidx.annotation.Nullable;
 
import com.example.androidprogressbar.R;
 
public class ScratchCard extends View {
 
    private Bitmap mBitmapBackground;
    private Bitmap mBitmapFront;
    private Canvas mCanvas;
    private Paint pathPaint;
    private Path path;
    private Paint mPaintText;
 
    public ScratchCard(Context context) {
        super(context);
        init();
    }
 
    public ScratchCard(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }
 
    public ScratchCard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
 
    private void init() {
        pathPaint = new Paint();
        pathPaint.setAlpha(0);
        pathPaint.setStyle(Paint.Style.STROKE);
        pathPaint.setStrokeWidth(70);
        pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));//混合模式
        pathPaint.setStrokeJoin(Paint.Join.ROUND);//线段之间连接处的样式
        pathPaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔的线冒样式
        path = new Path();
        mBitmapBackground = BitmapFactory.decodeResource(getResources(), R.drawable.card);
        mCanvas = new Canvas();
        mPaintText = new Paint();
        mPaintText.setColor(Color.WHITE);
        mPaintText.setTextSize(100);
        mPaintText.setStrokeWidth(20);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmapBackground, 0, 0, null);
        canvas.drawBitmap(mBitmapFront, 0, 0, null);
    }
 
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmapBackground = getBitmap(mBitmapBackground, w, h);
        mBitmapFront = Bitmap.createBitmap(mBitmapBackground.getWidth(),
                mBitmapBackground.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmapFront);
        drawText(mCanvas, w, h);
    }
 
    @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;
    }
 
    private void drawText(Canvas canvas, int mWidth, int mHeight) {
        String text = "赶紧刮开吧";
        canvas.drawColor(Color.GRAY);
        Paint.FontMetrics fm = mPaintText.getFontMetrics();
        int mTxtWidth = (int) mPaintText.measureText(text, 0, text.length());
        int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
        int x = mWidth / 2 - mTxtWidth / 2; //文字在画布中的x坐标
        int y = mHeight / 2 + mTxtHeight / 4; //文字在画布中的y坐标
        canvas.drawText(text, x, y, mPaintText);
    }
 
    public Bitmap getBitmap(Bitmap bm, int newWidth, int newHeight) {
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
        return newbm;
    }
 
}

以上就是Android通过自定义view实现刮刮乐效果详解的详细内容,更多关于Android刮刮乐的资料请关注编程网其它相关文章!

--结束END--

本文标题: Android通过自定义view实现刮刮乐效果详解

本文链接: https://www.lsjlt.com/news/144222.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android通过自定义view实现刮刮乐效果详解
    目录前言实现原理关键步骤创建bitmap绘制文字画路径完整代码前言 已经有两个月没有更新博客了,其实这篇文章我早在两个月前就写好了,一直保存在草稿箱里没有发布出来。原因是有一些原理性...
    99+
    2022-11-13
  • 基于Android自定义控件实现刮刮乐效果
     只是简单的实现了效果,界面没怎么做优化,不过那都是次要的啦!!相信大家都迫不及待的想看效果图了吧, 其中主要的彩票视图类和橡皮擦类都是通过代码的方式构建视图,布局...
    99+
    2022-06-06
    Android
  • Android App中实现简单的刮刮卡抽奖效果的实例详解
    主要思想: 将一个view设计成多层:背景层,含中奖信息等; 遮盖层,用于刮奖,使用关联一个Bitmap的Canvas 在该Bitmap上,使用它的canvas.drawPat...
    99+
    2022-06-06
    刮刮卡 app Android
  • Android 通过自定义view实现水波纹效果案例详解
    在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她; 在这样的关键时候,身...
    99+
    2022-11-12
  • Android中怎么通过自定义view实现TopBar效果
    这篇文章给大家介绍Android中怎么通过自定义view实现TopBar效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。布局文件<xml version="1.0" en...
    99+
    2023-05-30
    android view topbar
  • Android自定义View实现动画效果详解
    目录帧动画补间动画属性动画帧动画 帧动画就是给定一个完整动画的所有关键帧,由大脑想象中间的变化过程的一种动画。 <xml version="1.0" encoding="utf...
    99+
    2023-02-02
    Android自定义View实现动画 Android 动画 Android自定义View
  • 怎么在Android中通过自定义view实现滑动解锁效果
    怎么在Android中通过自定义view实现滑动解锁效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。自定义view如下@SuppressLint("Clicka...
    99+
    2023-06-15
  • Android中怎么通过自定义View实现圆形切图效果
    本篇文章给大家分享的是有关Android中怎么通过自定义View实现圆形切图效果,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。实现思路使用一个Paint,将得到的Bitmap设...
    99+
    2023-05-30
  • Android自定义View实现纵向跑马灯效果详解
    首先看看效果图(录制的gif有点卡,真实的效果还是很流畅的) 实现思路 通过上面的gif图可以得出结论,其实它就是同时绘制两条文本信息,然后通过动画不断的改变两条文本信息...
    99+
    2022-06-06
    view 跑马灯 Android
  • Android自定义view实现滑动解锁效果
    本文实例为大家分享了Android自定义view实现滑动解锁的具体代码,供大家参考,具体内容如下 1. 需求如下: 近期需要做一个类似屏幕滑动解锁的功能,右划开始,左划暂停。 2. ...
    99+
    2022-11-12
  • android自定义view实现钟表效果
    本文实例为大家分享了android view实现钟表的具体代码,供大家参考,具体内容如下 先看效果图: 自定义view大家肯定已经不陌生了,所以直接今天直接步入正题:如何利用...
    99+
    2022-06-06
    view Android
  • Android自定义View实现扫描效果
    本文实例为大家分享了Android自定义View实现扫描效果的具体代码,供大家参考,具体内容如下 演示效果如下: 实现内容: 1、控制动画是竖向或者横向 2、控制动画初始是从底部/...
    99+
    2022-11-12
  • Android自定义View实现时钟效果
    本文实例为大家分享了Android自定义View实现时钟效果的具体代码,供大家参考,具体内容如下 自定义时钟 初学自定义View,先画一个不太成熟的时钟(甚至只有秒针) 时钟效果 ...
    99+
    2022-11-12
  • 怎么在Android中通过自定义View实现一个抽屉效果
    怎么在Android中通过自定义View实现一个抽屉效果?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Android 自定义View实现抽屉效果说明这个自定义V...
    99+
    2023-05-31
    android view roi
  • 怎么在Android中通过自定义View实现一个扫描效果
    这篇文章给大家介绍怎么在Android中通过自定义View实现一个扫描效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。自定义属性:<declare-styleable name="ScanV...
    99+
    2023-06-14
  • Android中怎么通过自定义view实现进度条加载效果
    Android中怎么通过自定义view实现进度条加载效果,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。分析图:代码如下:package com.example.d...
    99+
    2023-05-30
    android view
  • Android中自定义view实现侧滑效果
    效果图: 看网上的都是两个view拼接,默认右侧的不显示,水平移动的时候把右侧的view显示出来。但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高...
    99+
    2022-06-06
    view 自定义view Android
  • Android自定义Animation实现View摇摆效果
    使用自定义Animation,实现View的左右摇摆效果,如图所示: 代码很简单,直接上源码 activity_maini.xml布局文件: <?xml v...
    99+
    2022-06-06
    view animation Android
  • Android自定义View实现折线图效果
    下面就是结果图(每种状态用一个表情图片表示): 一、主页面的布局文件如下: <RelativeLayout xmlns:android="http://schema...
    99+
    2022-06-06
    折线图 view Android
  • Android自定义View实现打字机效果
    一、先来看看效果演示 二、实现原理: 这个其实不难实现,通过一个定时器不断调用TextView的setText就行了,在setText的时候播放打字的音效。 具体代码如下:...
    99+
    2022-06-06
    view 打字机 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作