Android多种样式的进度条


---- The mark of the immature man is that he wants to die nobly for a causer while the mark of the mature man is that he wants to live humbly for one 



1. 水平向右的进度条



1-1 定义显示进度指示的图形 

drawable目录下progress_v_01.xml

关于shape使用详情可 查阅 点击打开链接

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!--默认图形大小-->
    <size
        android:width="500dp"
        android:height="50dp" />
    <!--填充颜色 -->
    <solid android:color="#6633CC" />
    <!--边框角度›-->
    <corners android:radius="20dp" />
</shape>

效果图 1-1-1



1-2. 在drawable目录下新建一个clip标签的文件 
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/progress_v_01"
    android:gravity="left">

</clip>

clipOrientation设置方向为水平方向

gravity设置过程中对齐方式为左

drawable 中引用要显示设置的图形 


1-3.在页面布局文件中使用 

在src属性下引入我们1-2中创建的clip标签的文件 

<ImageView
        android:layout_margin="10dp"
        android:background="#e6e6e6"

        android:id="@+id/iv_image_clip_left"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"     
        android:src="@drawable/clip_left_01"/>
   


1.4 在java代码中动态设置进度 


 private ImageView mClipLeftImageView;
    

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

        mClipLeftImageView = (ImageView) findViewById(R.id.iv_image_clip_left);
        mClipLeftImageView.setImageLevel(10000);

        handler.postDelayed(runnable,2000);
    }
    private int mUnmber = 0;
    private Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {

            if (mUnmber<=10000){
                mClipLeftImageView.getDrawable().setLevel(mUnmber);
                handler.postDelayed(runnable,20);
                mUnmber+=100;
            }
        }
    };


2. 水平向左的进度条


2-1 定义显示进度的图片,这里使用的是1-1中定义的图形 

2-2 创建clip标签文件 

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/progress_v_01"
    android:gravity="right"
    >
</clip>

clipOrientation设置方向为水平方向

gravity设置过程中对齐方式为右(从而达到进度从右向左的实现效果)

drawable 中引用要显示设置的图形 

2-3 在布局文件中的使用 同1-3;

2-4  java代码中的设置同 1-4;



3.水平向左向右的进度条


3-1 定义显示进度的图片,这里使用的是1-1中定义的图形 

3-2 创建clip标签文件 

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/progress_v_01"
    android:gravity="center_horizontal"
    >
</clip>

clipOrientation设置方向为水平方向

gravity设置过程中对齐方式 为垂直中心对齐(从而达到进度从中间向两边扩展的实现效果)

drawable 中引用要显示设置的图形 


3-3 在布局文件中的使用 同 1-3;

3-4 在java代码中的设置同 1-4;





4.水平向右的圆形进度条


4-1 定义使用到的显示进度的图形 drawbale目录下progress_oval_01.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <!--设置黑夜显示大小-->
    <size
        android:width="100dp"
        android:height="100dp" />
    <!--设置图形颜色-->
    <gradient
        android:centerColor="#CC9933"
        android:centerX="0.5"
        android:centerY="0.5"
        android:endColor="#33FF33"
        android:gradientRadius="45"
        android:startColor="#FFFF33"
        android:type="radial" />
    <!--设置图形边框-->
    <stroke
        android:width="2dp"
        android:color="#0000CC" />
    
</shape>


4-2 创建使用到的clip文件 

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/progress_oval_01"
    android:gravity="left"
    >

</clip>

clipOrientation设置方向为水平方向

gravity设置过程中对齐方式 为左边对齐(从而达到进度从左边向右的扩展的实现效果)

drawable 中引用要显示设置的图形 


3-3 在布局文件中的使用 同 1-3;

3-4 在java代码中的设置同 1-4;




5. 中心向外扩展的圆形进度条

5-1 创建显示进度的图形 这里引用的是4-1中创建的图形

5-2 创建对应显示的clip标签文件 

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal|vertical"
    android:drawable="@drawable/progress_oval_01"
    android:gravity="center"
    >

</clip>


clipOrientation设置方向为水平方向

gravity设置过程中对齐方式 为中心对齐(从而达到进度从中间向两边的扩展的实现效果)

drawable 中引用要显示设置的图形 


5-3 在布局文件中的使用 同 1-3;

创建ImageView标签,在src属性下进行引用

5-4 在java代码中的设置同 1-4;



6.垂直向上的直线进度条

6-1 创建显示进度的图形 

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <size android:width="5dp"
        android:height="100dp"/>

    <gradient
        android:angle="45"
        android:startColor="#FF9900"
        android:centerColor="#FFFF00"
        android:endColor="#66FF00"
        />
    <corners android:radius="5dp"/>

</shape>


效果图: 6-1-1



6-2 创建对应的clip标签文件 

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="vertical"
    android:drawable="@drawable/progress_oval_01"
    android:gravity="bottom"
    >

</clip>

clipOrientation设置方向为竖直方向

gravity设置过程中对齐方式 底部(从而达到进度从底部向上增加的实现效果)

如果设置为top,那么进度将成为从上到下 

drawable 中引用要显示设置的图形 

6-3 在布局文件中的使用 同 1-3;

创建ImageView标签,在src属性下进行引用

6-4 在java代码中的设置同 1-4;






7.垂直向上的圆形进度条



8 Clip方式实现综述  

ClipDrawable代表从其它位图上截取一个“图片片段”。在XML文件中使用<clip.../>元素定义ClipDrawable对象,
可指定如下三个属性:

android:drawable:指定截取的源Drawable对象,也可以指定drawable类的子标签

android:clipOrientation:指定截取的方向,可设置为 horizontal  vertical 

android:gravity:指定截取时的对齐方式,可设置为top bottom right center_vertical fill_vertical center_horizontal center  fill  clip_vertaical  start end 等等


使用ClipDrawable对象时可以调用setLevel(int level)方法来设置截取的区域大小,当level为0时,截取的图片片段为空;当level为10000时,截取整张图片。


可以使用Cli pDrawable的这种性质控制截取图片的区域大小,让程序不断调用setLevel方法并改变level的值,达到让图片慢慢展开的效果



9 通过自定义View的方式来实现进度条 -水平进度条


效果图 8-1 

看这样的进度条确实有点风骚,不过效果还行

9-1 定义一个类,继承ProgressBar

public class HorizontalProgressBarWithNumber extends ProgressBar {


    public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs,
                                           int defStyle) {
        super(context, attrs, defStyle);

        
    }

    @Over

官方推荐的使用方式为

public class HorizontalProgressBarWithNumber extends ProgressBar {


    public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs,
                                           int defStyle) {
        super(context, attrs, defStyle);

        mPaint.setTextSize(mTextSize);
        mPaint.setColor(mTextColor);
    }

    @Over

也就是说g..官方推荐的使用两个构造参数去调用三个构造参数的写法,我个人不建议这样写,两个构造去调用三个构造的方法,那么有时我们在构造中进行初时化操作的时候只需要在三个构造参数的方法进行一次初始化操作就好,但是当我们开发的应用遇到低版本的手机时,会遇到崩溃的问题(无法加载初始化xml布局文件),因为三个构造的方法是在高版本中才有的,所以我这里将初始化的操作全部封装到另一个方法中去,分别在两个构造中和三个构造方法中调用。

9-2 复写父控件的onDraw方法,来进行重新绘制 

 @Override
    protected synchronized void onDraw(Canvas canvas) {

        canvas.save();
        /**
         * 定义画笔的初始位置
         */
        canvas.translate(getPaddingLeft(), getHeight() / 2);

        /**
         * 计算加载进度的比例
         */
        float radio = getProgress() * 1.0f / getMax();
        /**
         * 计算已加载的进度
         */
        float progressPosX = (int) (mRealWidth * radio);
        /**
         * 定义进度上显示的文字信息
         */
        String text = getProgress() + "%";


        /**
         * 获取绘制文字的宽与高
         */
        float textWidth = mPaint.measureText(text);
        float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;

        /**
         * 判断绘制
         */
        if (progressPosX + textWidth > mRealWidth) {
            progressPosX = mRealWidth - textWidth;
        }


        /**
         * 绘制已加载的进度
         */

        mPaint.setColor(mBarColor);
        mPaint.setStrokeWidth(mProgressBarHeight);
        canvas.drawLine(0, 0, progressPosX, 0, mPaint);


        /**
         * 绘制加载显示的文字
         */
        mPaint.setColor(mTextColor);
        canvas.drawText(text, progressPosX, -textHeight, mPaint);


        /**
         * 绘制未加载的进度
         */
        float start = progressPosX + textWidth;
        mPaint.setColor(mUnBarColor);
        mPaint.setStrokeWidth(mProgressBarHeight);
        canvas.drawLine(start, 0, mRealWidth, 0, mPaint);


        canvas.restore();

    }

这里进行绘制的过程是 先绘制已加载的进度,然后再绘制显示进度的文字,最后再绘制滑加载的进度,

9-3 设置并初始化相关的变量

其中使用到一些变量,比如绘制文字的颜色,绘制进度的颜色,高度等等。

这里使用的方法是在成员变量中进行了设置默认的值

    /**
     * 定义一个画笔
     */
    protected Paint mPaint = new Paint();
    /**
     * 设置默认的显示进度文字的颜色
     */
    protected int mTextColor = 0xff253688;
    /**
     * 设置显示默认的显示进度的文字的大小
     */
    protected int mTextSize = sp2px(10);

    /**
     * 设置默认的绘制进度条的高度
     */
    protected int mProgressBarHeight = dp2px(10);

    /**
     * 设置默认的绘制进度条颜色
     */
    protected int mBarColor = 0xffffcc00;
    /**
     * 未加载进度条的颜色
     */
    protected int mUnBarColor = 0xffe6e6e6;

    /**
     * 绘制进度条的实际宽度
     */
    protected int mRealWidth;

第一个变量是我们绘制过程中使用到的画笔,我们这里在类加载的时候进行了初时化操作,同时也给这个画笔设置一些对应的属性值


    
    
    private  void  initFunction(){
        
        mPaint.setTextSize(mTextSize);
        mPaint.setColor(mTextColor);


    }
    


我们这里设置的是显示文字的大小与颜色(如果用到测量的话,在测量的时候可能会用到要测量绘制文字的大小,而我们这里是通过画笔的属性进行测量的)


变量mRealWidth是我们实际中需要绘制的进度条的实际宽度,可以在onMeaure方法中进行初始化(请查看下面的代码块)

也可以在方法中进行初始化

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        
        mRealWidth = w-getPaddingLeft()-getPaddingRight();
        
    }


其他的相应变量就是一些颜色与大小 ,其中有一个个将dp值转为px值的方法和sp转为px的方法(这是一些工具类) 

    /**
     * dp 2 px
     *
     * @param dpVal
     */
    protected int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

    /**
     * sp 2 px
     *
     * @param spVal
     * @return
     */
    protected int sp2px(int spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, getResources().getDisplayMetrics());

    }
走到这里,我们的自定义进度条就可以使用了

当然我们可以设置初始化这些变量的值

 /**
     * 设置已绘制的进度条的颜色
     *
     * @param mBarColor
     */
    public void setmBarColor(int mBarColor) {
        this.mBarColor = mBarColor;
    }

    /**
     * 设置过度条的高度
     *
     * @param mProgressBarHeight
     */
    public void setmProgressBarHeight(int mProgressBarHeight) {
        this.mProgressBarHeight = mProgressBarHeight;
    }

    /**
     * 设置指示进度条的显示文字的颜色
     *
     * @param mTextColor
     */
    public void setmTextColor(int mTextColor) {
        this.mTextColor = mTextColor;
    }

    /**
     * 设置指示进度条进度的显示文字的颜色
     *
     * @param mTextSize
     */
    public void setmTextSize(int mTextSize) {
        this.mTextSize = mTextSize;
    }

    /**
     * 设置未加载进度条处的进度颜色
     *
     * @param mUnBarColor
     */
    public void setmUnBarColor(int mUnBarColor) {
        this.mUnBarColor = mUnBarColor;
    }

9-4 自定义属性方式设置初始化变量值 


也可以通过自定义属性的方式来进行操作

values文件夹下attrs.xml文件中 

定义自定义属性 :绘制文本的颜色

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="HorizonProgressBarWidthNumber">
        <attr name="textProColor" format="color" />
    </declare-styleable>

</resources>


在构造方法中获取到自定义属性的值,并进行相应的赋值操作

    /**
     * 获取自定义属性操作
     * @param context
     * @param attrs
     * @param defStyle
     */
    private void initFunction(Context context, AttributeSet attrs, int defStyle) {
        
        final TypedArray attributes = getContext().obtainStyledAttributes(
                attrs, R.styleable.HorizonProgressBarWidthNumber);

        mTextColor = attributes.getColor(R.styleable.HorizonProgressBarWidthNumber_textProColor, 0xff000000);
    }


9-5 onMeasure方法中的测量

在onMeasure方法进行一些测量

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec,
                                          int heightMeasureSpec) {


        /**
         * 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
         * 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
         * 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)
         */

        /**
         * 三种测量模式
         * UNSPECIFIED:父布局没有给子布局任何限制,子布局可以任意大小。
         * EXACTLY:父布局决定子布局的确切大小。不论子布局多大,它都必须限制在这个界限里。
         * AT_MOST:子布局可以根据自己的大小选择任意大小。
         */

        /**
         * 获取测量宽度大小
         */
        int width = MeasureSpec.getSize(widthMeasureSpec);
        /**
         * 对高度进度测量
         */
        int height = 0;

        /**
         * 获取高度的测量模式
         */
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        /**
         * 获取测量高度的大小
         */
        int specSize = MeasureSpec.getSize(heightMeasureSpec);
        /**
         * 判断如果是非精准度的,那么就进行测量大小的重新设定
         */
        if (specMode == MeasureSpec.EXACTLY) {
            height = specSize;
        } else {
            /**
             * 获取显示加载进度的显示文本的宽度与高度
             */
            float textHeight = (mPaint.descent() - mPaint.ascent());
            /**
             * 计算测量的高度
             */
            height = (int) (getPaddingTop() + getPaddingBottom() + Math.max(
                    mProgressBarHeight, Math.abs(textHeight)));
            if (specMode == MeasureSpec.AT_MOST) {
                height = Math.min(height, specSize);
            }
        }
        /**
         * 设置测量
         */
        setMeasuredDimension(width, height);

        /**
         * 获取实际需要绘制进度条的宽度
         */
        mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
    }


9-6 风骚进度条设置使用

使用:

在xml中引入控件 

在java代码中

public class CustomProgressActivity extends Activity {

    private HorizontalProgressBarWithNumber mProgressBarView;
   

    private int mNumber = 0;
 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_progress);
        mProgressBarView = (HorizontalProgressBarWithNumber) findViewById(R.id.custom_progress_view);
        mProgressBarView.setMax(100);

       
        handler.sendEmptyMessage(1001);
       

    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            
            if (msg.what == 1001) {
                mProgressBarView.setmBarColor(randomColor());
                mProgressBarView.setProgress(mNumber);
                if (mNumber > 100) {
                    handler.removeMessages(1001);
                }
                if (mNumber < 100) {
                    handler.sendEmptyMessageDelayed(1001, 300);
                }
              
                mNumber++;

            }
           
        }
    };


    public  int randomColor(){
        Random random = new Random();
        //如果值太大,会偏白,太小则会偏黑,所以需要对颜色的值进行范围限定
        int red = random.nextInt(150)+50;//50-199
        int green = random.nextInt(150)+50;//50-199
        int blue = random.nextInt(150)+50;//50-199
        return Color.rgb(red, green, blue);//根据rgb混合生成一种新的颜色
    }


}

到这里就可以设置比较风骚的水平进度条了,我这里只是动态改变了绘制已加载进度条的颜色


10 通过自定义View的方式来实现进度条 -圆形进度条


效果图 10-1


    

        写作过程同 9 ,主要是在onDraw方法中进行的绘制

	@Override
	protected synchronized void onDraw(Canvas canvas)
	{


		/**
		 * 获取显示进度的文字指示
		 */
		String text = getProgress() + "%";
		/**
		 * 获取显示进度的文字的宽与高
		 */
		float textWidth = mPaint.measureText(text);
		float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;

		canvas.save();
		/**
		 * 将画布移动到中心
		 */
		canvas.translate(getPaddingLeft() + mProgressBarHeight / 2, getPaddingTop()
				+ mProgressBarHeight / 2);
		mPaint.setStyle(Style.STROKE);
		/**
		 * 绘制未加载的进度
		 */
		mPaint.setColor(mUnReachedBarColor);
		mPaint.setStrokeWidth(mProgressBarHeight);
		canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);

		/**
		 * 绘制已加载的圆环进度
		 */

		mPaint.setColor(mReachedBarColor);
		mPaint.setStrokeWidth(mProgressBarHeight);
		float sweepAngle = getProgress() * 1.0f / getMax() * 360;
		canvas.drawArc(new RectF(0, 0, mRadius * 2, mRadius * 2), 0,
				sweepAngle, false, mPaint);

		/**
		 * 绘制显示进行的颜色
		 */
		mPaint.setStyle(Style.FILL);
		canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight,
				mPaint);

		canvas.restore();

	}

相关的变量说明

	/**
	 * 定义设置进度圆的默认半径
	 */
	private int mRadius = dp2px(30);

	/**
	 * 圆环的默认宽度
	 */
	private  int mProgressBarHeight = dp2px(5);

	/**
	 * 声明初始化一个画笔
	 */
	private Paint mPaint = new Paint();
	/**
	 * 设置未加载进度的默认颜色
	 */
	private int mUnReachedBarColor = 0xffe6e6e6;

	/**
	 * 设置已加载进度的默认颜色
	 */
	private int mReachedBarColor = 0xff89cc99;


	/**
	 * 设置进度已加载进度条的颜色
	 * 这里只写了这个设置颜色
	 * 当然也可以写出代码动态设置改变 未加载进度条的颜色
	 * 还有显示文字的颜色 
	 * 还有进度条的宽度等等
	 * @param color
	 */
	public void setReachedBarColor(int color){
		this.mReachedBarColor = color;
	}
	

相关的构造方法以及构造方法中的初始化操作

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

	public RoundProgressBar(Context context, AttributeSet attrs)
	{
		this(context, attrs,0);
	}

	public RoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		mPaint.setStyle(Style.STROKE);
		mPaint.setAntiAlias(true);
		mPaint.setDither(true);
		mPaint.setStrokeCap(Cap.ROUND);
	}


代码中的使用


public class MainActivity extends Activity {

    private  int number =0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final RoundProgressBar progress1 = (RoundProgressBar)findViewById(R.id.progress1);
        progress1.setMax(100);

        final RoundProgressBar progress2 = (RoundProgressBar)findViewById(R.id.progress2);
        progress2.setMax(100);

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (number>10){
                    progress2.setReachedBarColor(0xff00FF00);
                }else if (number>10){
                    progress2.setReachedBarColor(0xff00FF00);
                }else if (number>20){
                    progress2.setReachedBarColor(0xff228B22);
                }else if (number>30){
                    progress2.setReachedBarColor(0xff008000);
                }else if (number>40){
                    progress2.setReachedBarColor(0xff006400);
                }else if (number>50){
                    progress2.setReachedBarColor(0xff483D8B);
                }else if (number>60){
                    progress2.setReachedBarColor(0xff8A2BE2);
                }else if (number>70){
                    progress2.setReachedBarColor(0xff4B0082);
                }else if (number>90){
                    progress2.setReachedBarColor(0xff8B008B);
                }
                progress2.setProgress(number);
                progress1.setProgress(number);
                number+=1;
            }
        }, 0, 100);
    }
}


可以看到这里是随着进度不断的设置加载进度条的绘制颜色

关于计时器Timer与TimerTask使用 可以点击查看


使用ClipDrawble实现图片的缩放


效果图:


在这里是使用的Clipdrawable 类的api来实现的

    private int number =0;

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


        imageView = (ImageView) findViewById(R.id.imageView);
     

        ClipDrawable clipDrawable = new ClipDrawable(getResources().getDrawable(R.mipmap.dff), Gravity.CENTER_HORIZONTAL,ClipDrawable.HORIZONTAL);
        
        clipDrawable.setLevel(1000);
        
        imageView.setImageDrawable(clipDrawable);


        final Timer timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if(number<10000){

                    MainActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            imageView.getDrawable().setLevel(number);
                            number+=40;
                            
                        }
                    });

                }else{
                    timer.cancel();
                }

            }
        },0,30);

    }


14 绘画使用相关基础 :

绘制使用到的统一的宽度与高度  


    private int mWidth = 200;
    private int mHeight = 200;

   


14-1 绘制一个矩形 

14-1-1 绘制单色的矩形

效果图:14-1 -1


   
        
        /**
         * 创建图片
         */
        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        /**
         * 创建画布
         */
        Canvas canvas = new Canvas(bitmap);

        /**
         * 创建画笔
         */
        Paint paint = new Paint();

        /**
         * 设置画笔的颜色
         */
        paint.setColor(Color.parseColor("#ff6600"));
        /**
         * 绘制矩形背景
         * Draw the specified Rect using the specified paint. The rectangle will
         * be filled or framed based on the Style in the paint.
         *
         * @param left   The left side of the rectangle to be drawn
         * @param top    The top side of the rectangle to be drawn
         * @param right  The right side of the rectangle to be drawn
         * @param bottom The bottom side of the rectangle to be drawn
         * @param paint  The paint used to draw the rect
         * public void drawRect ( float left, float top, float right, float bottom,
         * @NonNull Paint paint){
         * native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
         *  }
         */
        canvas.drawRect(0, 0, mWidth, mHeight, paint);

        canvas.drawRect(0, 0, mWidth, mHeight, paint);

        /**
         * 绘制显示的文字
         */
        Paint textPaint = new Paint();
        textPaint.setColor(Color.BLUE);
        /**
         * 设置搞锯齿
         */
        textPaint.setAntiAlias(true);
        textPaint.setTextSize(15);
        /**
         * 设置绘制的字体样式
         * The default NORMAL typeface object
                public static final Typeface DEFAULT;
         * The default BOLD typeface object. Note: this may be not actually be bold, depending on what fonts are installed. Call getStyle() to knowfor sure.
                public static final Typeface DEFAULT_BOLD;
         * The NORMAL style of the default sans serif typeface.
                public static final Typeface SANS_SERIF;
         *  The NORMAL style of the default serif typeface.
                public static final Typeface SERIF;
         * The NORMAL style of the default monospace typeface.
            public static final Typeface MONOSPACE;
        */
        textPaint.setTypeface(Typeface.DEFAULT);
        /**
         * 设置文字的对齐方式 
         */
        
        textPaint.setTextAlign(Paint.Align.CENTER);
        /**
         * Draw the text, with origin at (x,y), using the specified paint. The
         * origin is interpreted based on the Align setting in the paint.
         *
         * @第一个参数 text  The text to be drawn
         * @第二个参数 x     The x-coordinate of the origin of the text being drawn
         * @第三个参数 y     The y-coordinate of the baseline of the text being drawn
         * @第四个参数 paint The paint used for the text (e.g. color, size, style)
         */
        canvas.drawText("hollow", mWidth / 2, 20, textPaint);

        /**
         * 分别绘制不同样式的文字
         */
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
        canvas.drawText("DEFAULT_BOLD", mWidth / 2, 45, textPaint);
        
        textPaint.setTypeface(Typeface.SANS_SERIF);
        canvas.drawText("SANS_SERIF", mWidth / 2, 66, textPaint);
        
        textPaint.setTypeface(Typeface.SERIF);
        canvas.drawText("SERIF", mWidth / 2, 96, textPaint);
        
        textPaint.setTypeface(Typeface.MONOSPACE);
        canvas.drawText("MONOSPACE", mWidth / 2, 116, textPaint);
        

        /**
         * 将绘制的图片设置显示
         */
        imageView.setImageBitmap(bitmap);

在这里设置绘制出来的矩形颜色为 #00ff66 
当然我们也可以绘制出来相应的具有渐变效果的矩形,我们只需要将上面的paint.setColor()这个方法进行相应的替换


14-1-2 绘制渐变效果的矩形

效果图 14-1-2:


        /**
         * 创建图片
         */
        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        /**
         * 创建画布
         */
        Canvas canvas = new Canvas(bitmap);

        /**
         * 创建画笔
         */
        Paint paint = new Paint();
        /**
         * 创建背景使用到的渐变颜色
         */

        int[] colors = new int[]{Color.YELLOW, Color.GREEN, Color.BLUE};
        /**
         * 定义渐变开始的位置信息
         */
        float[] postions = new float[]{0f, 0.5f, 1.0f};
        /**
         * 创建渐变背景
         */
        //水平方向线性渐变
        LinearGradient linearGradient = new LinearGradient(0, 0, mWidth, mHeight, colors, postions, Shader.TileMode.REPEAT);

        SweepGradient sweepGradient = new SweepGradient(mWidth / 2, mHeight / 2, colors, postions);

        /**
         * 将渐变的背景设置旋转45度,设置为水平方向的渐变
         */
        Matrix matrix = new Matrix();
        matrix.setRotate(45, mWidth / 2, mHeight / 2);


        linearGradient.setLocalMatrix(matrix);

        paint.setShader(linearGradient);

        canvas.drawRect(0, 0, mWidth, mHeight, paint);


        /**
         * 将绘制的图片设置显示
         */
        imageView.setImageBitmap(bitmap);


    }


14-2 绘制多个点 

效果图:14-2



 /**
         * 创建图片
         */
        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        /**
         * 创建画布
         */
        Canvas canvas = new Canvas(bitmap);

        /**
         * 创建画笔
         */
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#ff6600"));
        /**
         * 画矩形背景
         */
        canvas.drawRect(0, 0, mWidth, mHeight, paint);

        /**
         * 画点操作
         */
        //定义点的位置
        float[] pts = new float[]{
                10, 10,
                20, 20,
                30, 30,
                50, 50
        };
        //设置画出的点的颜色为白色
        paint.setColor(Color.parseColor("#ffffff"));
        //设置画笔的宽度
        paint.setStrokeWidth(2);
        //画点操作
        canvas.drawPoints(pts, 0, pts.length, paint);
        //将画出的图形设置显示到ImageView上
        imageView.setImageBitmap(bitmap);



14-3 绘制多条直线 


效果图:14-3



 
        
        Bitmap bimap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bimap);
        Paint paint = new Paint();

        paint.setColor(Color.parseColor("#ff6600"));
        /**
         * 画矩形背景
         */
        canvas.drawRect(0, 0, mWidth, mHeight, paint);

        /**
         * 画直线
         * 每一条直线都是由两个点构成,而每个点则是由两个坐标构成
         */

        float[] floats = new float[]{
                50, 50, 180, 50,
                50, 80, 180, 80,
                50, 100, 190, 100
        };

        paint.setStrokeWidth(5);
        paint.setColor(Color.WHITE);

        /**
         * 画多条直线
         */
        canvas.drawLines(floats, 0, floats.length, paint);

        imageView.setImageBitmap(bimap);

  



14-4 绘制椭圆或者圆  

效果图:14-4 



        Bitmap bimap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bimap);
        Paint paint = new Paint();

        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#ff6600"));
        /**
         * 画矩形背景
         */
        canvas.drawRect(0, 0, mWidth, mHeight, paint);

        paint.setColor(Color.WHITE);
        /**
         * 定义矩形的大小
         */
        RectF rect = new RectF();
        rect.left = 10;
        rect.top = 10;
        rect.right = 100;
        rect.bottom = 100;

        /**
         * 当对应的值设置成为一定的极限后,就会出现相应的圆形 或者 是椭圆
         */
        /**
         * 设置四个角在x轴方向与y轴方向的角度
         */
        float roatx = 10;
        float roaty = 10;
        /**
         * 绘制椭圆 或者 是圆形
         */
        canvas.drawRoundRect(rect, roatx, roaty, paint);


        RectF rect1 = new RectF();
        rect1.left = 100;
        rect1.top = 10;
        rect1.right = 200;
        rect1.bottom = 110;

        /**
         * 设置的角度正好的宽与高的一半
         * 将画出圆形
         */
        float roatx1 = 50;
        float roaty2 = 50;

        canvas.drawRoundRect(rect1, roatx1, roaty2, paint);



15-5 绘制一个时钟

效果图:15-5 



15-5-1 绘制表盘 

   /**
     * 绘制表盘
     */
    private Bitmap drawDail() {
        
        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();

        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(5);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);

        canvas.save();

        /**
         * 绘制外周表盘
         */

        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2 - 10, paint);

        /**
         * 绘制中心点圆
         */

        paint.setStyle(Paint.Style.FILL);

        canvas.drawCircle(mWidth / 2, mHeight / 2, 5, paint);


        /**
         * 绘制刻度
         */
        paint.setColor(Color.BLACK);

        /**
         * 这里采用的绘制方式是只绘制竖直方向上的一条直线,每绘制一次就将整个画布旋转30度
         */
        for (int i = 0; i < 12; i++) {
            if (i % 3 == 0) {
                paint.setStrokeWidth(5);
                canvas.drawLine(mWidth / 2, 13, mWidth / 2, 23, paint);
            } else {
                paint.setStrokeWidth(3);
                canvas.drawLine(mWidth / 2, 13, mWidth / 2, 20, paint);
            }

            canvas.rotate(30, mWidth / 2, mHeight / 2);
        }
        /**
         * 到这里我们基本的一个表盘就已经绘制出来了
         */
        canvas.restore();
        

        return bitmap;

    }

15-5-2:绘制指针

 private Bitmap drawModelSign(Bitmap bitmap) {

        Bitmap bitmap1 = Bitmap.createBitmap(bitmap);
        Canvas canvas = new Canvas(bitmap1);

        paint.setAntiAlias(true);
        paint.setColor(Color.YELLOW);
        paint.setStrokeWidth(5);


        /**
         * 获取时间数据
         */
        Calendar calendar = Calendar.getInstance();
        int hours = calendar.get(Calendar.HOUR);
        int second = calendar.get(Calendar.SECOND);
        int minute = calendar.get(Calendar.MINUTE);

        /**
         * 指针的长度
         */
        float length = mHeight / 2;
        /**
         * 旋转角度
         */

        float degrees = 0;
        /**
         * 时针
         */
        canvas.save();

        degrees = 30 * hours + minute / 60 * 30;
        canvas.rotate(degrees, mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 2, mHeight / 2, mWidth / 2, length * 8 / 10, paint);

        canvas.restore();
        /**
         * 分针
         */
        canvas.save();
        paint.setStrokeWidth(3);
        degrees = 6 * minute + second / 60 * 6;
        canvas.rotate(degrees, mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 2, mHeight / 2, mWidth / 2, length * 6 / 10, paint);
        canvas.restore();
        /**
         * 秒针
         */
        canvas.save();
        paint.setStrokeWidth(2);
        degrees = 6 * second;
        canvas.rotate(degrees, mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 2, mHeight / 2 + 20, mWidth / 2, length * 3 / 10, paint);
        canvas.restore();


        /**
         * 绘制显示24小时格式的时间 文字
         */
        canvas.save();
        paint.setStrokeWidth(2);
        paint.setColor(Color.RED);
        String text = calendar.get(Calendar.HOUR_OF_DAY) + ":" + minute + ":" + second;
        /**
         * Draw the text, with origin at (x,y), using the specified paint. The
         * origin is interpreted based on the Align setting in the paint.
         *
         * @param text  The text to be drawn
         * @param x     The x-coordinate of the origin of the text being drawn
         * @param y     The y-coordinate of the baseline of the text being drawn
         * @param paint The paint used for the text (e.g. color, size, style)
         */
        canvas.drawText(text, mWidth / 2 - 25, mHeight / 2 - 45, paint);
        canvas.restore();


        return bitmap1;
    }


15-5-3 创建动态的时钟 

    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (timer != null) {
            timer.cancel();
        }

    }

    private int mWidth = 200;
    private int mHeight = 200;
    private Timer timer;
    private Bitmap bitmap;

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


        imageView = (ImageView) findViewById(R.id.imageView);
        

        /**
         * 获取表盘
         */
        bitmap = drawDail();


        /**
         * 创建定时器
         */
        timer = new Timer();
        /**
         * 每间隔一秒时间来绘制一次
         */
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Bitmap bitmaps = drawModelSign(bitmap);
                        imageView.setImageBitmap(bitmaps);
                    }
                });


            }
        }, 0, 1000);
    }

  


































  • 10
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早起的年轻人

创作源于分享

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值