編輯:關於Android編程
最近在慕課網,學習了關於進度條的自定義,有直線型和圓形進度條兩種:
需要的文件value目錄下的attrs.xml:
1 直線型進度條:
public class MyProgressBar extends ProgressBar {
//默認值
private static final int DEFAULT_TEXT_SIZE = 10; //sp
private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;
private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA;
private static final int DEFAULT_HEIGHT_UNREACH = 2; //dp
private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
private static final int DEFAULT_HEIGHT_REACH = 2;//dp
private static final int DEFAULT_TEXT_OFFSET = 10;//dp
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
protected int mTextColor = DEFAULT_TEXT_COLOR;
protected int mUnReachColor = DEFAULT_COLOR_UNREACH;
protected int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
protected int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
protected int mReachColor = DEFAULT_COLOR_REACH;
protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);
//
protected Paint mPaint = new Paint();
protected int mRealWidth;//控件的寬度
public MyProgressBar(Context context) {
this(context,null);
// TODO Auto-generated constructor stub
}
public MyProgressBar(Context context, AttributeSet attrs) {
this(context, attrs,0);
// TODO Auto-generated constructor stub
}
public MyProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
obtainStyleAttrs(attrs);
}
/**
* 獲取自定義屬性
* @param attrs
*/
private void obtainStyleAttrs(AttributeSet attrs) {
// TODO Auto-generated method stub
TypedArray typedArray = getContext()
.obtainStyledAttributes(attrs, R.styleable.MyProgressBar);
//獲取各個屬性
mTextSize = (int) typedArray.getDimension(R.styleable.MyProgressBar_propgress_text_size,
mTextSize);
mTextColor = (int)typedArray.getColor(R.styleable.MyProgressBar_propgress_text_color,
mTextColor);
mUnReachColor = (int)typedArray.getColor(R.styleable.MyProgressBar_propgress_unreach_color,
mUnReachColor);
mUnReachHeight = (int)typedArray.getDimension(R.styleable.MyProgressBar_propgress_unreach_height,
mUnReachHeight);
mReachColor = (int)typedArray.getColor(R.styleable.MyProgressBar_propgress_reach_color,
mReachColor);
mReachHeight = (int)typedArray.getDimension(R.styleable.MyProgressBar_propgress_reach_height,
mReachHeight);
mTextOffset = (int)typedArray.getDimension(R.styleable.MyProgressBar_propgress_text_offset,
mTextOffset);
typedArray.recycle();
//設置mpaint要測量的值
//如果忘記的話,字體就設置不了了
mPaint.setTextSize(mTextSize);
}
/**
* 測量
*/
@Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//寬度測量,有點特殊,由於這裡的寬度不確定,所以
//int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int withValue = MeasureSpec.getSize(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
//這裡設定寬度和高度
setMeasuredDimension(withValue, height);
//繪制的實際的寬度
mRealWidth = getMeasuredWidth()-getPaddingLeft()-getPaddingRight();
}
@Override
protected synchronized void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.save();
canvas.translate(getPaddingLeft(), getHeight()/2);
boolean noNeedUnReach = false;
// 繪制ReachBar
String text = getProgress()+"%";
int textWidth = (int) mPaint.measureText(text);
float radio = getProgress()*1.0f/getMax();
float progressX = radio*mRealWidth;//進度條的長度
if(progressX+textWidth>mRealWidth){
progressX = mRealWidth - textWidth;
noNeedUnReach = true;
}
float endX = progressX - mTextOffset/2;
if(endX>0){
mPaint.setColor(mReachColor);
mPaint.setStrokeWidth(mReachHeight);
canvas.drawLine(0, 0, endX, 0, mPaint);//繪制一條線
}
//繪制文本Text
mPaint.setColor(mTextColor);
int y = (int) (-(mPaint.descent()+mPaint.ascent())/2);//設置文本顯示居中
canvas.drawText(text, progressX, y, mPaint);
//繪制UnReachBar
if(!noNeedUnReach){
float start = progressX+mTextOffset/2+textWidth;
mPaint.setColor(mUnReachColor);
mPaint.setStrokeWidth(mUnReachHeight);
canvas.drawLine(start, 0, mRealWidth, 0, mPaint);
}
canvas.restore();
}
private int measureHeight(int heightMeasureSpec) {
// TODO Auto-generated method stub
int result =0;
int Mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
//如果mode為一精確值
if(Mode==MeasureSpec.EXACTLY){
result = size;
}else{
//獲取組件中最大高度
int textHeight = (int) (mPaint.descent()-mPaint.ascent());
result = getPaddingTop()
+getPaddingBottom()
+Math.max(Math.max(mUnReachHeight, mReachHeight), Math.abs(textHeight));
//不能超過最大值
if(Mode==MeasureSpec.AT_MOST){
result = Math.min(size,result);
}
}
return result;
}
//dp轉化
protected int dp2px(int dpValue){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dpValue, getResources().getDisplayMetrics());
}
//sp轉化
protected int sp2px(int spValue){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spValue, getResources().getDisplayMetrics());
}
}
2 圓形進度條:
public class RoundProgressBar extends ProgressBar {
//默認值
private static final int DEFAULT_TEXT_SIZE = 10; // sp
private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;
private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA;
private static final int DEFAULT_HEIGHT_UNREACH = 2; // dp
private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
private static final int DEFAULT_HEIGHT_REACH = 2;// dp
private static final int DEFAULT_TEXT_OFFSET = 10;// dp
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
protected int mTextColor = DEFAULT_TEXT_COLOR;
protected int mUnReachColor = DEFAULT_COLOR_UNREACH;
protected int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
protected int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
protected int mReachColor = DEFAULT_COLOR_REACH;
protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);
private Paint mPaint = new Paint();
private int mRdius = dp2px(30);
private int mMaxPaintWith;
// dp轉化
protected int dp2px(int dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpValue, getResources().getDisplayMetrics());
}
// sp轉化
protected int sp2px(int spValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spValue, getResources().getDisplayMetrics());
}
public RoundProgressBar(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}
public RoundProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
//Reach進度條加粗,為unReach進度條的2.0f倍
mReachHeight = (int) (mUnReachHeight * 2.0f);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.RoundProgressBar);
// 獲取各個屬性
mTextSize = (int) ta.getDimension(
R.styleable.RoundProgressBar_progress_text_size, mTextSize);
mTextColor = (int) ta.getColor(
R.styleable.RoundProgressBar_progress_text_color, mTextColor);
mUnReachColor = (int) ta.getColor(
R.styleable.RoundProgressBar_progress_unreach_color,
mUnReachColor);
mUnReachHeight = (int) ta.getDimension(
R.styleable.RoundProgressBar_progress_unreach_height,
mUnReachHeight);
mReachColor = (int) ta.getColor(
R.styleable.RoundProgressBar_progress_reach_color, mReachColor);
mReachHeight = (int) ta.getDimension(
R.styleable.RoundProgressBar_progress_reach_height,
mReachHeight);
mTextOffset = (int) ta.getDimension(
R.styleable.RoundProgressBar_progress_text_offset, mTextOffset);
mRdius = (int) ta.getDimension(R.styleable.RoundProgressBar_radius,
mRdius);
mPaint.setStyle(Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStrokeCap(Cap.ROUND);
ta.recycle();
//忘記這個字體就無法設置了
mPaint.setTextSize(mTextSize);
}
/**
* 測量
*/
@Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMaxPaintWith = Math.max(mUnReachHeight, mReachHeight);
// 默認四個panding一致
int expected = mRdius * 2 + mMaxPaintWith + getPaddingLeft()
+ getPaddingRight();
// 圓形進度條提供了測量的方法
int width = resolveSize(expected, widthMeasureSpec);
int height = resolveSize(expected, heightMeasureSpec);
int realWidth = Math.min(width, height);
mRdius = (realWidth - getPaddingLeft() - getPaddingRight() - mMaxPaintWith) / 2;
setMeasuredDimension(realWidth, realWidth);
}
@Override
protected synchronized void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
String text = getProgress() + "%";
float textWidth = mPaint.measureText(text);
float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;
canvas.save();
// 坐標
canvas.translate(getPaddingLeft() + mMaxPaintWith / 2, getPaddingTop()
+ mMaxPaintWith / 2);
mPaint.setStyle(Style.STROKE);
// unReachBar
mPaint.setColor(mUnReachColor);
mPaint.setStrokeWidth(mUnReachHeight);
canvas.drawCircle(mRdius, mRdius, mRdius, mPaint);
// reachBar
mPaint.setColor(mReachColor);
mPaint.setStrokeWidth(mReachHeight);
// 弧度
float sweepAngle = getProgress() * 1.0f / getMax() * 360;
// 畫弧
canvas.drawArc(new RectF(0, 0, mRdius * 2, mRdius * 2), 0, sweepAngle,
false, mPaint);
// text
mPaint.setColor(mTextColor);
mPaint.setStyle(Style.FILL);
canvas.drawText(text, mRdius - textWidth / 2, mRdius - textHeight,
mPaint);
// 別忘
canvas.restore();
}
}
然後我們在MainActivity中實現效果:
public class MainActivity extends Activity {
private MyProgressBar myProgressBar;
private RoundProgressBar myRoundProgressBar;
private static final int MSG_UPDATE = 0X01;
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
//直線進度條
int progress = myProgressBar.getProgress();
myProgressBar.setProgress(++progress);
//圓形進度條
int roundProgress = myRoundProgressBar.getProgress();
myRoundProgressBar.setProgress(++roundProgress);
if(progress>=100 ){
handler.removeMessages(MSG_UPDATE);
}
if(roundProgress>=100){
handler.removeMessages(MSG_UPDATE);
}
handler.sendEmptyMessageDelayed(MSG_UPDATE, 200);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myProgressBar = (MyProgressBar)findViewById(R.id.myprogressBar1);
myRoundProgressBar = (RoundProgressBar) findViewById(R.id.roundProgressBar);
handler.sendEmptyMessage(MSG_UPDATE);
}
}
應用:
定義控件成功之後,直接在.xml文件中引入並設置,如在activity_main.xml中
在這裡需要注意的是:必須添加這個指定xmlns,否則用不了
xmlns:hyman="http://schemas.android.com/apk/res/com.example.progressbar"
最後的效果顯示如下:
第一次編譯時,設定android SDK:F:\RAD Studio XE6\PlatformSDKs\adt-bundle-windows-x86-20131030\s
今天測試發現了游戲的一個問題,系統郵件,如果發了tab,在android上一打開郵件內容就會crash。而且他們很確定是tab的問題。 憑我多個月的經驗(確實
本文實例介紹的Android的Gallery控件是個很不錯的看圖控件,可以大大減輕開發者對於看圖功能的開發,並且效果也很美觀。本文實例中的Gallery的用法,主要實現用
使用意圖傳遞數據的幾種方式 點此獲取完整代碼 我們除了要從活動返回數據,也常常要傳遞數據給活動。對此我們可以使用Intent對象將這些數據傳遞給目標活動。