文章目录
前言
自定义View有多种实现类型,分别为继承自View完全自定义,继承自现有控件(如ImageView)实现特定效果,继承自ViewGroup实现布局类.这里面涉及到View的测量和布局,View的绘制,处理触摸事件,动画等.
这次实现自定义圆形进度条,我使用的是继承LinearLayout的方式.最终的实现效果如下:
我的想法
要实现这个简单的效果,我的想法是,将circle_progress_view作为背景,进度条用Paint画一条弧实现,作为子组件.只要当前进度发生变化,就进行重绘.
circle_progress_view.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="70dp" android:layout_height="70dp" android:layout_alignParentRight="true" android:gravity="center" android:orientation="vertical">
<ImageView android:id="@+id/cpv_iv_icon" android:layout_width="32dp" android:layout_height="32dp" android:src="@drawable/ic_download" />
<TextView android:id="@+id/cpv_tv_des" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="下载" />
</LinearLayout>
|
关于onDraw和dispatchDraw
绘制View本身的内容,调用View.onDraw方法;绘制自己的孩子,则通过dispatchDraw来实现.
View组件的绘制先是调用draw方法绘制背景,在画完背景之后,draw方法会调用onDraw,然后是调用dispatchDraw方法,分发子组件的绘制.
上面有提到,将circle_progress_view作为背景,将弧形进度条作为子组件,所以只要在dispatchDraw方法中加入对弧形进度条的绘制就行了,很简单!
扫描二维码关注公众号,回复:
7404864 查看本文章
CircleProgressView.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
package com.yongf.circleprogressview;
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView;
public class extends LinearLayout {
private ImageView mIcon; private TextView mDesc;
private boolean mProgressEnable = true; private long mMax = 100; private long mProgress;
public (Context context) { this(context, null); }
public (Context context, AttributeSet attrs) { this(context, attrs, 0); }
public (Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);
View view = View.inflate(context, R.layout.circle_progress_view, this);
mIcon = (ImageView) view.findViewById(R.id.cpv_iv_icon); mDesc = (TextView) view.findViewById(R.id.cpv_tv_des); }
public void setIcon(int resId) { mIcon.setImageResource(resId); }
public void setDesc(String desc) { mDesc.setText(desc); }
public void setProgressEnable(boolean progressEnable) { mProgressEnable = progressEnable; }
public void setMax(long max) { mMax = max; }
public void setProgress(long progress) { mProgress = progress;
invalidate(); }
@Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas);
if (mProgressEnable) { RectF oval = new RectF(mIcon.getLeft(), mIcon.getTop(), mIcon.getRight(), mIcon.getBottom()); float startAngle = -90;
float sweepAngle = mProgress * 360.f / mMax;
boolean useCenter = false;
Paint paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setAntiAlias(true); canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
} } }
|
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
xml version="1.0" encoding="utf-8"?> <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<com.yongf.circleprogressview.CircleProgressView android:id="@+id/cpv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" " /> </RelativeLayout>
|
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
package com.yongf.circleprogressview;
import android.os.AsyncTask; import android.os.Bundle; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
final CircleProgressView cpv = (CircleProgressView) findViewById(R.id.cpv); cpv.setDesc("下载"); cpv.setIcon(R.drawable.ic_pause);
cpv.setProgressEnable(true); cpv.setMax(100);
cpv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new AsyncTask<Void, Integer, Void>() { int i = 0;
@Override protected Void doInBackground(Void... params) { while (true) { publishProgress(i); SystemClock.sleep(100); if (i >= 100) { break; } i++; } return null; }
@Override protected void onProgressUpdate(Integer... values) { Integer value = values[0]; cpv.setProgress(i); cpv.setDesc(i + "%"); } }.execute(); } }); } }
|
感谢
感谢访问我的个人博客的朋友,如果您感觉本站对您搜索的问题有所帮助,并感觉对本站还满意的话,顶一下吧,希望您把本站分享给您的朋友!在此对您表示由衷的谢意! :)
原文:大专栏 No48-【原】-自定义View之自定义圆形进度条