zoukankan      html  css  js  c++  java
  • Android刮刮卡自定义控件

    网上的都是自己绘制的或者图片,我的需求是可以随意的自定义底部和顶部的布局。所以自己重写一个,原理就是直接继承 View 来实现一个刮层,让这个刮层和图片以及文字不产生任何依赖,再结合 FrameLayout 将刮层放置最上一层,刮层之下你想放多少图片文字,图片文字要怎么布局摆放都行。由于是FrameLayout ,刮层的上面想加内容都是可以的。如图:

    原理:刮刮卡无非就是文本,或者图片,就是我们下边的布局,然后在其上绘制刮奖层,设置DST_OUT,然后把用户触摸绘制上去;这样消失以后就能看到背后的奖了。

    布局

     <FrameLayout
            android:layout_width="350dp"
            android:layout_centerInParent="true"
            android:layout_height="150dp">
            <include
                layout="@layout/scratch_view_after"/>
            <coordemo.ly.com.myapplication.GuaGuaKaView
                android:layout_width="match_parent"
                android:id="@+id/gg1"
                android:layout_height="match_parent" />
        </FrameLayout>
    

      

    刮一刮控件
    public class GuaGuaKaView extends View {
        /**
         * 绘制线条的画笔
         */
        private Paint mOutterPaint = new Paint();
        /**
         * 遮层画笔
         */
        private Paint mMaskPaint = new Paint();
        /**
         * 最下面画笔
         */
        private Paint mBackPint = new Paint();
        /**
         * mCanvas绘制内容在其上
         */
        private Bitmap mBitmap;
        /**
         * 记录用户绘制的Path
         */
        private Path mPath = new Path();
        /**
         * 内存中创建的Canvas
         */
        private Canvas mCanvas;
        private boolean isComplete;
        private Rect mTextBound = new Rect();
        private String mText = "¥500,0000";
        private int mLastX;
        private int mLastY;
        private int measuredWidth;
        private int measuredHeight;
        public GuaGuaKaView(Context context) {
            this(context, null);
        }
        public GuaGuaKaView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
        public GuaGuaKaView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
        private void init() {
            mPath = new Path();
            setUpOutPaint();
            setUpBackPaint();
        }
        /**
         * 初始化canvas的绘制用的画笔
         */
        private void setUpBackPaint() {
            mBackPint.setStyle(Style.FILL);
            mBackPint.setTextScaleX(2f);
            mBackPint.setColor(Color.DKGRAY);
            mBackPint.setTextSize(32);
            mBackPint.getTextBounds(mText, 0, mText.length(), mTextBound);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            if (!isComplete) {
                drawPath();
                canvas.drawBitmap(mBitmap, 0, 0, null);
            } else {
                this.setVisibility(GONE);
            }
        }
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            measuredWidth = getMeasuredWidth();//宽高和父view的相同
            measuredHeight = getMeasuredHeight();
            // 初始化bitmap
            mBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
            mMaskPaint.setColor(Color.parseColor("#00000000"));//遮层透明
            mMaskPaint.setStyle(Style.FILL);
            mCanvas.drawRoundRect(new RectF(0, 0, measuredWidth, measuredHeight), 0, 0, mMaskPaint);
            mCanvas.drawBitmap(BitmapFactory.decodeResource(getResources(),
                    R.drawable.award_1), null, new RectF(0, 0, measuredWidth, measuredHeight), null);//遮层
        }
        /**
         * 设置画笔的一些参数
         */
        private void setUpOutPaint() {
            // 设置画笔
    //         mOutterPaint.setAlpha(0);
            mOutterPaint.setColor(Color.parseColor("#c0c0c0"));
            mOutterPaint.setAntiAlias(true);
            mOutterPaint.setDither(true);
            mOutterPaint.setStyle(Style.STROKE);
            mOutterPaint.setStrokeJoin(Paint.Join.ROUND); // 圆角
            mOutterPaint.setStrokeCap(Paint.Cap.ROUND); // 圆角
            // 设置画笔宽度
            mOutterPaint.setStrokeWidth(50);
        }
        /**
         * 绘制线条
         */
        private void drawPath() {
            mOutterPaint.setStyle(Style.STROKE);
            mOutterPaint
                    .setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));//取俩者的交集
            mCanvas.drawPath(mPath, mOutterPaint);
        }
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int action = event.getAction();
            int x = (int) event.getX();
            int y = (int) event.getY();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    mLastX = x;
                    mLastY = y;
                    mPath.moveTo(mLastX, mLastY);
                    break;
                case MotionEvent.ACTION_MOVE:
                    int dx = Math.abs(x - mLastX);
                    int dy = Math.abs(y - mLastY);
                    if (dx > 3 || dy > 3)
                        mPath.lineTo(x, y);
                    mLastX = x;
                    mLastY = y;
                    new Thread(mRunnable).start();
                    break;
                case MotionEvent.ACTION_UP:
                    new Thread(mRunnable).start();
                    break;
            }
            invalidate();
            return true;
        }
        /**
         * 统计擦除区域任务
         */
        private Runnable mRunnable = new Runnable() {
            private int[] mPixels;
            @Override
            public void run() {
                int w = getWidth();
                int h = getHeight();
                float wipeArea = 0;
                float totalArea = w * h;
                Bitmap bitmap = mBitmap;
                mPixels = new int[w * h];
                /**
                 * 拿到所有的像素信息
                 */
                bitmap.getPixels(mPixels, 0, w, 0, 0, w, h);
                /**
                 * 遍历统计擦除的区域
                 */
                for (int i = 0; i < w; i++) {
                    for (int j = 0; j < h; j++) {
                        int index = i + j * w;
                        if (mPixels[index] == 0) {
                            wipeArea++;
                        }
                    }
                }
                /**
                 * 根据所占百分比,进行一些操作
                 */
                if (wipeArea > 0 && totalArea > 0) {
                    int percent = (int) (wipeArea * 100 / totalArea);
    //                Log.e("TAG", percent + "");
                    if (percent > 50) {
    //                    Log.e("TAG", "清除区域达到50%,下面自动清除");
                        isComplete = true;
                        postInvalidate();
                    }
                }
            }
        };
        /**
         * 将布局转换成bitmap
         * @param addViewContent
         * @return
         */
        private Bitmap getViewBitmap(View addViewContent) {
            addViewContent.setDrawingCacheEnabled(true);
            addViewContent.measure(
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            addViewContent.layout(0, 0,
                    addViewContent.getMeasuredWidth(),
                    addViewContent.getMeasuredHeight());
            addViewContent.buildDrawingCache();
            Bitmap cacheBitmap = addViewContent.getDrawingCache();
            Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
            return bitmap;
        }
    }
    

      

     
    GitHub地址:
     
     
     
     
     
     
  • 相关阅读:
    Java数据结构和算法总结-数组、二分查找
    Android开发必知--使用View.setId的正确姿势
    Fiddler基本用法以及如何对手机抓包
    Android学习笔记(十四)方便实用的首选项-PreferenceActivity
    Android学习笔记(十三)SharedPreference必须掌握的基础
    设计模式之单例模式
    关于如何控制一个页面的Ajax读数据只读一次的简单解决办法!
    ASP.NET MVC 表单提交多层子级实体集合数据到控制器中
    使用Bootstrap的popover标签中嵌入插件,并且为插件注册事件实现Ajax与后台交互
    关于.Net使用企业库访问MySql数据库
  • 原文地址:https://www.cnblogs.com/sixrain/p/7323352.html
Copyright © 2011-2022 走看看