一个圆形的进度显示控件,用圆中扇形的角度大小来表示进度信息
开源组件来自:http://p.codekk.com/detail/Android/timqi/SectorProgressView
直接拿取SectorProgressView.java类和attr.xml使用,复制到自己的项目中,
效果图:
进度百分比和起始角度都可以设置
在res/values 文件下定义一个attrs.xml 文件:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SectorProgressView"> <attr name="bgColor" format="color"/> <attr name="fgColor" format="color"/> <attr name="percent" format="float"/> <attr name="startAngle" format="float"/> </declare-styleable> </resources>
自定义SectorProgressView
package com.example.sectorprogressviewdemo; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; public class SectorProgressView extends View { private int bgColor; private int fgColor; private float startAngleBg, lengthAngleBg, startAngleFg, lengthAngleFg; private Paint bgPaint; private Paint fgPaint; private RectF oval; public SectorProgressView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SectorProgressView, 0,0); try { bgColor = a.getColor(R.styleable.SectorProgressView_bgColor, 0xffe5e5e5); fgColor = a.getColor(R.styleable.SectorProgressView_fgColor, 0xffff765c); percent = a.getFloat(R.styleable.SectorProgressView_percent, 0); startAngle = a.getFloat(R.styleable.SectorProgressView_startAngle, 0); computeArcArgs(startAngle, percent); } finally { a.recycle(); } init(); } private void computeArcArgs(float startAngle, float percent) { this.lengthAngleFg = percent*36/10; this.lengthAngleBg = 360-lengthAngleFg; this.startAngleFg = startAngle; this.startAngleBg = startAngleFg +lengthAngleFg; } private void init() { bgPaint = new Paint(); bgPaint.setColor(bgColor); fgPaint = new Paint(); fgPaint.setColor(fgColor); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); float xpad = (float)(getPaddingLeft()+getPaddingRight()); float ypad = (float)(getPaddingBottom()+ getPaddingTop()); float wwd = (float)w - xpad; float hhd = (float)h - ypad; oval = new RectF(getPaddingLeft(), getPaddingTop(), getPaddingLeft()+wwd, getPaddingTop()+hhd); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawArc(oval, startAngleBg, lengthAngleBg, true, bgPaint); canvas.drawArc(oval, startAngleFg, lengthAngleFg, true, fgPaint); } public int getBgColor() { return bgColor; } public void setBgColor(int bgColor) { this.bgColor = bgColor; refreshTheLayout(); } public int getFgColor() { return fgColor; } public void setFgColor(int fgColor) { this.fgColor = fgColor; refreshTheLayout(); } private void refreshTheLayout() { invalidate(); requestLayout(); } private float percent; public float getStartAngle() { return startAngle; } public void setStartAngle(float startAngle) { this.startAngle = startAngle; computeArcArgs(startAngle, percent); invalidate(); requestLayout(); } public float getPercent() { return percent; } public void setPercent(float percent) { this.percent = percent; computeArcArgs(startAngle, percent); invalidate(); requestLayout(); } private float startAngle; }布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" 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"> <com.example.sectorprogressviewdemo.SectorProgressView android:id="@+id/spv" android:layout_width="280dp" android:layout_height="280dp" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" app:bgColor="#e5e5e5" app:fgColor="#CD3700" app:percent="25" app:startAngle="0" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/llStartAngle" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="startAngle: " /> <SeekBar android:id="@+id/sbStartAngle" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:id="@+id/llPercent" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@id/llStartAngle" android:layout_marginBottom="20dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" percent: " /> <SeekBar android:id="@+id/sbPercent" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:textAppearance="?android:attr/textAppearanceSmall" android:id="@+id/tvTip" android:layout_below="@+id/spv" android:layout_centerHorizontal="true"/> </RelativeLayout>在main中使用:
package com.example.sectorprogressviewdemo; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; public class MainActivity extends Activity implements OnSeekBarChangeListener { private TextView tvTip; private SectorProgressView spv; private SeekBar sbPercent; private int percent; private SeekBar sbStartAngle; private int startAngle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvTip = (TextView) findViewById(R.id.tvTip); spv = (SectorProgressView) findViewById(R.id.spv); sbPercent = (SeekBar) findViewById(R.id.sbPercent); sbPercent.setMax(100); sbPercent.setProgress(25);//设置起始百分比 // sbPercent.setBackgroundColor(0xffCD3700);//xml中和java代码都可以设置 percent=25; sbStartAngle = (SeekBar) findViewById(R.id.sbStartAngle); sbStartAngle.setMax(360); sbStartAngle.setProgress(0);//设置起始角度 startAngle = 0; sbPercent.setOnSeekBarChangeListener(this); sbStartAngle.setOnSeekBarChangeListener(this); showTip(); } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub switch (seekBar.getId()) { case R.id.sbPercent: spv.setPercent(progress); percent=progress; break; case R.id.sbStartAngle: spv.setStartAngle(progress); startAngle=progress; break; default: break; } showTip(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } protected void showTip() { // TODO Auto-generated method stub tvTip.setText("percent: " + percent + "; startAngle: " + startAngle); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }