自定义View(本篇讲解Matrix,自定义属性),消蒙版小游戏

本文详细介绍了如何在Android应用中使用自定义属性、布局文件、View类及Activity实现复杂视图的绘制与交互,包括创建自定义视图类、设置属性、响应触摸事件和保存绘制结果。通过实例代码深入探讨了这些技术的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先说要求:实现如下效果

这里写图片描述
(由于电脑特别卡,看起来不流畅,在手机上试过很流畅的)

接下来说一下具体做法:

1、layout下的布局文件

</RelativeLayout><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mystyle="http://schemas.android.com/apk/res-auto"//声明自定义属性
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <com.my.administrator.zdyview.BitmapView2//这个名字BitmapView2要与view类名相同
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mystyle:myview_background="@mipmap/meinv4"//设置自定义属性
        mystyle:myview_paintwidth="30dp" />//设置自定义属性

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#ffccff"
        android:text="保存" />//点击保存按钮

</RelativeLayout>

2、写BitmapView2 类继承View,加构造器,重写onMeasure,onDraw方法,在onDraw方法里面画东西

public class BitmapView2 extends View {
    private int width;
    private int height;
    private Paint mPaintMeng;
    private Paint mPaintRect;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Bitmap mBitmapImage;
    private Matrix matrix;
    private Path mPath;
//两个构造器
    public BitmapView2(Context context) {
        super(context);
    }

    public BitmapView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        //下面几行代码是对自定义属性的设置
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.mystyle);//解析xml,解析方式为value文件夹下mystyle
        BitmapDrawable dra = (BitmapDrawable) a.getDrawable(R.styleable.mystyle_myview_background);//得到layout下xml文件传的myview_background
        if (dra != null) {//如果在xml中传入了图片
            mBitmapImage = dra.getBitmap();
        } else {//若没有传图片,则在下面设置添加
            mBitmapImage = BitmapFactory.decodeResource(getResources(), R.mipmap.me);
        }
        int paintWidth = a.getDimensionPixelOffset(R.styleable.mystyle_myview_paintwidth, 10);//得到xml中设置的画笔宽度属性,设置默认10
        mPaintMeng = new Paint();//画蒙板的画笔
        mPaintMeng.setColor(Color.GREEN);

        mPaintRect = new Paint();//画bitmap的画笔
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
        mPaintRect.setXfermode(mode);
        mPaintRect.setStrokeJoin(Paint.Join.ROUND);//设置连接部分样式
        mPaintRect.setStrokeCap(Paint.Cap.ROUND);//设置中间部分的样式
        mPaintRect.setStrokeWidth(paintWidth);//设置画笔宽度属性
        mPaintRect.setStyle(Paint.Style.FILL_AND_STROKE);//去掉锯齿

        matrix = new Matrix();//初始化矩阵
        mPath = new Path();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//设置Bitmap的大小
        mCanvas = new Canvas(mBitmap);//自定义的画布
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        matrix.reset();
        matrix.postScale((float) width / mBitmapImage.getWidth(), (float) height / mBitmapImage.getHeight());//放大到整个bitview界面
        canvas.drawBitmap(mBitmapImage, matrix, null);//图片
        mCanvas.drawRect(0, 0, width, height, mPaintMeng);//蒙板
        mCanvas.drawPath(mPath, mPaintRect);//画点击时的圆,画笔为XOR透明
        canvas.drawBitmap(mBitmap, 0, 0, null);//相当于底版
    }

    float x;
    float y;
    float old_x;
    float old_y;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = event.getX();
                y = event.getY();
                mPath.moveTo(x, y);
                invalidate();
                old_x = x;
                old_y = y;
                return true;
            case MotionEvent.ACTION_MOVE:
                x = event.getX();
                y = event.getY();
                mPath.moveTo(old_x, old_y);
                mPath.lineTo(x, y);//也可以写下面的代码
                // mPath.quadTo((x+old_x)/2,(y+old_y)/2,x,y);
                invalidate();
                old_x = x;
                old_y = y;
                break;
        }
        return super.onTouchEvent(event);
    }
}

3、Activity文件,布局文件中有保存按钮,实现点击按钮时保存当前的图片

public class MainActivity extends AppCompatActivity {
   private Button mButton;
   private  BitmapView2 bitmapView2;
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bitmapView2 = (BitmapView2) findViewById(R.id.view);
        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bitmapView2.setDrawingCacheEnabled(true);//要获取cache首先要通过setDrawingCacheEnable方法开启cache,
                // 然后再调用getDrawingCache方法就可以获得view的cache图片了。
                Bitmap bit = bitmapView2.getDrawingCache(true);
                File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");//保存图片到这个路径
                if(!file.exists()){
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    bit.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        });

4、在这个布局文件中用到了自定义属性,那么,怎样实现自定义属性?

《1》在values文件夹下新建resource file

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="mystyle">//styleable的名字
       //下面定义几个属性,包括名字和参数值类型
        <attr name="myview_background" format="reference"></attr>
        <attr name="myview_paintwidth" format="dimension|reference"></attr>
    </declare-styleable>
</resources>

《2》在layout的xml布局文件中声明,设置自定义属性,见layout下的布局文件加注释的部分
《3》在view类中解析layout下xml布局文件,解析方式为value文件夹下mystyle,并找到xml布局文件的设置。详情见上面BitmapView2类中对自定义属性的设置代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值