您的位置:首页 > 移动开发 > Android开发

Android自定义View之图形图像(模仿360的刷新球自定义一个SeekBar)

2015-09-18 21:43 477 查看

概述:

360安全卫士的那个刷新球(姑且叫它刷新球,因为真的不知道叫什么好,不是dota里的刷新球!!),里面像住了水一样,生动可爱,看似简单,写起来不太简单,本例程只是实现了它的部分功能而已,说实话,跟360的刷新球比起来差距还是很大,我这个长得有点挫。

本历程需要用到的知识包括:android的自定义View,自定义canvas、path、Bitmap、Handler

先结果演示:



Damo

public class MyPathView extends View {
    private int width;
    private int height;
    private int progress;
    private int maxProgress = 100;

    private Path mPath;
    private Paint mPaintCircle;
    private Paint mPaintWave;
    private Paint mPaintText;
    private Bitmap mBitmapBubble;
    private Canvas mCanvasBitmap;

    private int size = 0;//水波动幅度
    private int count;//水流动距离
    private boolean isAdd = true;
    private static final int START_W***E = 0x21;

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
        invalidate();
    }

    public int getMaxProgress() {
        return maxProgress;
    }

    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case START_W***E:
                    count += 30;
                    if (count >= 180) {
                        count = 0;
                    }
                    if (isAdd) {
                        size += 7;
                        if (size > 41) {
                            isAdd = false;
                        }
                    } else {
                        size -= 7;
                        if (size <= -41) {
                            isAdd = true;
                        }
                    }
                    invalidate();
                    sendEmptyMessageDelayed(START_W***E, 100);
                    break;
            }
        }
    };

    public MyPathView(Context context) {
        super(context);
    }

    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaintCircle = new Paint();
        mPaintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaintCircle.setColor(Color.argb(0X4f, 0x4d, 0x4d, 0xff));

        mPaintText = new Paint();
        mPaintText.setColor(Color.WHITE);
        mPaintText.setTextSize(50);
        mPaintText.setTextAlign(Paint.Align.CENTER);

        mPaintWave = new Paint();
        mPaintWave.setColor(Color.argb(0xaa, 0xff, 0x7c, 0x00));
        mPaintWave.setStyle(Paint.Style.FILL);
        //不显示非重叠部分,并且重叠部分显示自己
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);
        mPaintWave.setXfermode(mode);

        mPath = new Path();
        handler.sendEmptyMessageDelayed(START_W***E, 1000);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        mBitmapBubble = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvasBitmap = new Canvas(mBitmapBubble);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPath.reset();
        //canvas.drawColor(Color.argb(0xaa, 0x88, 0x7e, 0x7f));//自定义颜色
        mCanvasBitmap.drawCircle(width / 2, height / 2, 200, mPaintCircle);
        mPath.reset();
        //用path圈出一个矩形,把水波和球的包含进去
        mPath.moveTo(width / 2 + 200, height / 2 + 200 - progress / maxProgress * 400);
        mPath.lineTo(width / 2 + 200, height / 2 + 200);
        mPath.lineTo(0, height / 2 + 200);
        mPath.lineTo(0, height / 2 + 200 - progress / maxProgress * 400);
        /*
        画一条个模拟流动的波浪
         */
        //当count增大时,重绘会显示向前流动效果,count的值不能大于width/2-200
        mPath.lineTo(count, height / 2 + 200 -(float) progress / maxProgress * 400);
//        mPath.moveTo(count,200);
        //size的从大到小从小到大变化,重绘时会产生波浪起伏效果
        for (int i = 0; i < 20; i++) {
            /*
            rQuadTo()方法每次都会自动移动到下一位置,参数依次为水平幅度,
            垂直幅度,水平位移,处置位移
            */
            mPath.rQuadTo(20, size, 90, 0);
            mPath.rQuadTo(20, -size, 90, 0);
        }
        mPath.close();
        mCanvasBitmap.drawPath(mPath, mPaintWave);
        canvas.drawBitmap(mBitmapBubble, 0, 0, null);
        //绘制文本,当前进度
        canvas.drawText(progress*100/maxProgress+"%",width/2,height/2,mPaintText);

    }
}


主活动调用自定义View:

public class MainActivity extends Activity {
    private int progress;
    private Button mButtonStart;
    private MyPathView myPathView;

    private static final int DOWNLOAD_UPDATE = 0x99;
    //模拟下载
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //处理msg
            switch (msg.what) {
                case DOWNLOAD_UPDATE:
                    progress += 1;
                    //当progress大于maxProgress时,不再调用一下方法
                    if (progress<=myPathView.getMaxProgress()){
                        myPathView.setProgress(progress);//设置新的进度
                        sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 100);//每隔100毫秒发送一次handler
                    }
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mButtonStart = (Button) findViewById(R.id.button_start);
        myPathView = (MyPathView) findViewById(R.id.progress_view_first);

        mButtonStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //向handler发送一个延时空消息,1000毫秒后发送
                mHandler.sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 1000);
            }
        });

    }
}


布局调用自定义View:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Download"/>

    <com.example.administrator.selfdefinedview.widget.MyPathView
        android:id="@+id/progress_view_first"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: