1. 程式人生 > >Android UI高階之自定義控制元件

Android UI高階之自定義控制元件

在android中有許多控制元件,比如editview、button等,但是,有時這些控制元件並不能滿足我們的需求,這時,我們就需要去自定義一個控制元件來滿足我們的需要,下面給出一個仿360加速球的demo.

1、首先,來看一下360加速球的效果
這裡寫圖片描述

2、 下面給出一個自定義的view,加速球(Accelerating ball )

package com.example.houjie.studyapk.studyview.custom;

import android.annotation.TargetApi;
import android.content.Context;
import
android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.os.Build; import android.os.Handler; import android.os.Message; import
android.util.AttributeSet; import android.util.Log; import android.view.View; import java.util.Random; /** * 仿360加速球的自定義控制元件 * Created by hj on 2016/5/19. */ public class CustomViewAccBall extends View{ private Paint paintCircle,paintText,paintLine;//三個畫筆, private int r,width,height;//加速球的半徑,view的寬和高
private int dWidth,dHeight,bCount = 5,bHeight=50;//貝塞爾曲線的一些決定量,可以自己設定,我不太會用 private Random random;//產生隨機數,加速球的波浪效果 private Path path;// private final int maxProgress = 100;//當前的進度 private int progress=0; private Bitmap bitmap;//點陣圖 private Canvas bitmapCanvas;//點陣圖畫板 public int getProgress() { return progress; }// public void setProgress(int progress) { this.progress = progress; invalidate();//實時更新進度 } public int getMaxProgress() { return maxProgress; } //構造器,必須實現 public CustomViewAccBall(Context context) { super(context); init(); } public CustomViewAccBall(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CustomViewAccBall(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP)//取消版本限制 public CustomViewAccBall(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } private void init(){ //初始化圓的畫筆 paintCircle = new Paint(); paintCircle.setStrokeWidth(1); paintCircle.setAntiAlias(true); paintCircle.setColor(Color.argb(0xff,0x2b,0x84,0x62)); paintCircle.setStyle(Paint.Style.FILL); //初始化文字的畫筆 paintText = new Paint(); paintText.setTextSize(50f); paintText.setAntiAlias(true); paintText.setTextAlign(Paint.Align.CENTER); paintText.setColor(Color.WHITE); //初始化波浪線的畫筆 paintLine = new Paint(); paintLine.setStyle(Paint.Style.FILL); paintLine.setColor(Color.argb(0xff,0x4e,0xc8,0x63)); paintLine.setStrokeWidth(1); paintLine.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); // android.graphics.PorterDuff.Mode.SRC_IN:只在源影象和目標影象相交的地方繪製源影象 path = new Path(); //初始化path } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); bitmapCanvas.drawCircle(width/2,height/2,r,paintCircle);//繪製圓 //通過Path繪製貝塞爾曲線,此處貝塞爾曲線不是太懂,所以畫的東西不是太好,望高手指點 path.reset();//清除path內容 path.moveTo(0, height); path.lineTo(0, ((float) maxProgress-progress)/100*height);//此處若在定義時若是int,則必須強制轉換,否則結果為零,聰明的你一定能理解。 for (int i = 0; i < bCount; i++) { path.rQuadTo(random.nextFloat()*bHeight, random.nextFloat()*dWidth/2,random.nextFloat()*dWidth, 0); // path.rQuadTo(20, -5, 40, 0);//可以是這樣的固定值 } path.lineTo(width, ((float) maxProgress-progress)/100*((float)height)); Log.e("(maxProgrerogressheight","----------------"+((float) maxProgress-progress)/100*height); path.lineTo(width, height); path.close(); //將貝塞爾曲線繪製到Bitmap的Canvas上 bitmapCanvas.drawPath(path, paintLine); //將Bitmap繪製到View的Canvas上 bitmapCanvas.drawText(progress * 100f / maxProgress + "%", width / 2, height / 2, paintText); canvas.drawBitmap(bitmap, 0, 0, null); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = this.getMeasuredWidth();//得到寬和高 height = this.getMeasuredWidth(); setMeasuredDimension(width, height); r = width/2;//設定圓的半徑 dHeight = height/5; dWidth = width/5; bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//設定圖片的大小 bitmapCanvas = new Canvas(bitmap); random = new Random(); } }

3、activity佈局

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.example.houjie.studyapk.studyview.custom.ActivityCustomViewAccBall">
    <com.example.houjie.studyapk.studyview.custom.CustomViewAccBall
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:id="@+id/viewAccBall"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btnCustomAccBall"
        android:text="開啟動畫"
        />
</LinearLayout>

4、activity

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.example.houjie.studyapk.R;

/**
 * 仿360加速球顯示的activity
 */
public class ActivityCustomViewAccBall extends AppCompatActivity {
    private Button btnCustomAccBall;
    private CustomViewAccBall viewAccBall;
    private int i = 0;
    private  Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(i<=100){
                viewAccBall.setProgress(i);//延時1秒改變加速球進度
                sendEmptyMessageDelayed(1,1000);
                i+=10;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {


        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_activity_custom_view_acc_ball);
        viewAccBall = (CustomViewAccBall) findViewById(R.id.viewAccBall);
        btnCustomAccBall = (Button) findViewById(R.id.btnCustomAccBall);
        btnCustomAccBall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                i = 0;
                handler.sendEmptyMessageDelayed(1,1000);//開啟動畫
            }
        });
    }
}

5、效果
這裡寫圖片描述