1. 程式人生 > >android自定義顏色進度條ColorSeekBar

android自定義顏色進度條ColorSeekBar

      (尊重原創,轉載請說明來處,謝謝)

      最近做了一個背景是各種顏色的SeekBar,SeekBar顏色是漸變的,開始顏色、結尾顏色、以及按鈕的中間和邊框顏色都是可以自定義的,效果圖如下:

首先我要講解一下使用方式,第一、第三個ColorSeekBar是我用函式setColor()設定的顏色,第二個ColorSeekBar的顏色是預設的,大家請看使用程式碼:

xml:

<?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.lei.brightnessseekbar.MainActivity">

    <com.lei.brightnessseekbar.ColorSeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:layout_marginTop="30dp"/>
    <com.lei.brightnessseekbar.ColorSeekBar
        android:id="@+id/seekBar2"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:layout_marginTop="30dp"/>
    <com.lei.brightnessseekbar.ColorSeekBar
        android:id="@+id/seekBar3"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:layout_marginTop="30dp"/>

</LinearLayout>

JAVA:

package com.lei.brightnessseekbar;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private ColorSeekBar seekBar1,seekBar3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        seekBar1=(ColorSeekBar)findViewById(R.id.seekBar1);
        seekBar1.setColor(Color.RED, Color.BLUE, Color.WHITE, Color.YELLOW);
        seekBar3=(ColorSeekBar)findViewById(R.id.seekBar3);
        seekBar3.setColor(Color.BLUE,Color.GREEN,Color.WHITE,Color.GRAY);

    }
}
使用程式碼很簡單,有木有得意

下面我來講解一下思路:

1:首先呢要新建一個繼承自View的類,原因很簡單,你所看到的一切都是通過Canvas畫上去的,我這裡的類名為ColorSeekBar,並且重寫onDraw(),onMeasure(),onSizeChanged()方法(不要問我為什麼重寫他們,自定義控制元件必須的唄。。。)

@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec*2);
		setMeasuredDimension(widthSize, heightSize);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mRadius=h;
		x=h;//圓的橫座標
		sLeft = 0; // 背景左的座標
		sTop = h*0.25f;//top位置
		sRight = w; // 背景的寬的全部
		sBottom = h*0.75f; // 背景底部
		sWidth = sRight - sLeft; // 背景的寬度
		sHeight = sBottom - sTop; // 背景的高度
		RectF sRectF = new RectF(sLeft, sTop, sBottom, sBottom);
		sPath.arcTo(sRectF, 90, 180);
		sRectF.left = sRight - sBottom;
		sRectF.right = sRight;
		sPath.arcTo(sRectF, 270, 180);
		sPath.close();    // path準備背景的路徑
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		drawBackground(canvas);
		drawCircle(canvas);
		paint.reset();
	}

2:做好準備工作後我們就開始畫背景了,這是我畫背景的函式:

private void drawBackground(Canvas canvas){
		linearGradient=new LinearGradient(sLeft,sTop,sWidth,sHeight,colorArray,null, Shader.TileMode.REPEAT);
		paint.setAntiAlias(true);
		paint.setStyle(Style.FILL);
		//設定渲染器
		paint.setShader(linearGradient);
		canvas.drawPath(sPath, paint);
	}
其中的colorArray是顏色陣列,用於背景顏色的漸變
private int colorArray[]={startColor,endColor};
3:畫圓形按鈕函式:
private void drawCircle(Canvas canvas){
		Paint thumbPaint = new Paint();
		x =x<(mRadius/2)?(mRadius/2):x;//判斷thumb邊界
		x=x>sWidth-mRadius/2?sWidth-mRadius/2:x;
		thumbPaint.setStyle(Style.FILL);
		thumbPaint.setColor(thumbColor);
		canvas.drawCircle(x, mRadius / 2, mRadius / 2, thumbPaint);
		thumbPaint.setStyle(Style.STROKE);
		thumbPaint.setColor(thumbBorderColor);
		thumbPaint.setStrokeWidth(2);
		canvas.drawCircle(x, mRadius / 2, mRadius / 2, thumbPaint);
	}
好了,如果我現在說已經介紹完了,你們會不會打我吐舌頭

4:背景和圓形按鈕已經畫完,但是呢這個自定義控制元件還不能使用,原因很簡單:不是動態的唄,那我們就為它新增一個touch事件,並設定相應的接聽介面,當用戶手指滑動時可以動態移動顯示並且可以觸發相應事件:
public boolean onTouchEvent(MotionEvent event) {
		this.x = event.getX();
		progerss=(x-mRadius)/(sWidth-mRadius*2)*100;
		switch(event.getAction()) {

			case 0://ACTION_DOWN

				Log.i(TAG, "onTouchEvent: x: "+x+" y: "+y +" max : "+event.getSize()+" "+" "+sWidth);
				break;
			case 1://ACTION_UP
				if (onStateChangeListener!=null){
					onStateChangeListener.onStopTrackingTouch(progerss);
				}
				break;
			case 2://ACTION_MOVE

				if (onStateChangeListener!=null){
					onStateChangeListener.OnStateChangeListener(progerss);
				}
				this.invalidate();
				break;
		}
		return true;
	}

監聽介面:
public interface OnStateChangeListener{
		void OnStateChangeListener(float progress);
		void onStopTrackingTouch(float progress);
	}
	public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener1){
		this.onStateChangeListener=onStateChangeListener1;
	}

下面附上全部程式碼(2016/06/23日驗證可以使用):
package com.lei.brightnessseekbar;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * create  by lei
 */

public class ColorSeekBar extends View {

	private final String TAG="ColorSeekBar";
	private final Paint paint = new Paint();
	private final Path sPath = new Path();
	private float sLeft, sTop, sRight, sBottom;
	private float sWidth,sHeight;
	private LinearGradient linearGradient;
	private float x,y;
	private float mRadius;
	private float  progerss;
	private OnStateChangeListener onStateChangeListener;
	private int startColor=Color.BLACK;
	private int endColor=Color.WHITE;
	private int thumbColor=Color.BLACK;
	private int thumbBorderColor=Color.WHITE;
	private int colorArray[]={startColor,endColor};


	public ColorSeekBar(Context context) {
		this(context, null);
	}

	public void setColor(int startColor,int endColor,int thumbColor,int thumbBorderColor){
		this.startColor=startColor;
		this.endColor=endColor;
		this.thumbColor=thumbColor;
		this.thumbBorderColor=thumbBorderColor;
		colorArray[0]=startColor;
		colorArray[1]=endColor;
	}

	public ColorSeekBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		setLayerType(LAYER_TYPE_SOFTWARE, null);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec*2);
		setMeasuredDimension(widthSize, heightSize);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mRadius=h;
		x=h;//圓的橫座標
		sLeft = 0; // 背景左的座標
		sTop = h*0.25f;//top位置
		sRight = w; // 背景的寬的全部
		sBottom = h*0.75f; // 背景底部
		sWidth = sRight - sLeft; // 背景的寬度
		sHeight = sBottom - sTop; // 背景的高度
		RectF sRectF = new RectF(sLeft, sTop, sBottom, sBottom);
		sPath.arcTo(sRectF, 90, 180);
		sRectF.left = sRight - sBottom;
		sRectF.right = sRight;
		sPath.arcTo(sRectF, 270, 180);
		sPath.close();    // path準備背景的路徑
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		drawBackground(canvas);
		drawCircle(canvas);
		paint.reset();
	}

	public boolean onTouchEvent(MotionEvent event) {
		this.x = event.getX();
		progerss=(x-mRadius)/(sWidth-mRadius*2)*100;
		switch(event.getAction()) {

			case 0://ACTION_DOWN

				Log.i(TAG, "onTouchEvent: x: "+x+" y: "+y +" max : "+event.getSize()+" "+" "+sWidth);
				break;
			case 1://ACTION_UP
				if (onStateChangeListener!=null){
					onStateChangeListener.onStopTrackingTouch(progerss);
				}
				break;
			case 2://ACTION_MOVE

				if (onStateChangeListener!=null){
					onStateChangeListener.OnStateChangeListener(progerss);
				}
				this.invalidate();
				break;
		}
		return true;
	}

	private void drawCircle(Canvas canvas){
		Paint thumbPaint = new Paint();
		x =x<(mRadius/2)?(mRadius/2):x;//判斷thumb邊界
		x=x>sWidth-mRadius/2?sWidth-mRadius/2:x;
		thumbPaint.setStyle(Style.FILL);
		thumbPaint.setColor(thumbColor);
		canvas.drawCircle(x, mRadius / 2, mRadius / 2, thumbPaint);
		thumbPaint.setStyle(Style.STROKE);
		thumbPaint.setColor(thumbBorderColor);
		thumbPaint.setStrokeWidth(2);
		canvas.drawCircle(x, mRadius / 2, mRadius / 2, thumbPaint);
	}

	private void drawBackground(Canvas canvas){
		linearGradient=new LinearGradient(sLeft,sTop,sWidth,sHeight,colorArray,null, Shader.TileMode.REPEAT);
		paint.setAntiAlias(true);
		paint.setStyle(Style.FILL);
		//設定渲染器
		paint.setShader(linearGradient);
		canvas.drawPath(sPath, paint);
	}

	public interface OnStateChangeListener{
		void OnStateChangeListener(float progress);
		void onStopTrackingTouch(float progress);
	}
	public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener1){
		this.onStateChangeListener=onStateChangeListener1;
	}

}