andorid自定义progress

一直觉得android的progress不太好看,想改造一下,参考了github上https://github.com/feiyangxiaomi/ProgressWheel/

       

第一个图是改造前的android自带的progress,后面的三个是改造后的progress,显然改造后的progress更加的灵活,同时也展现的比较美观。具体实现方法非常的简单,这里从界面到程序的介绍流程。

在我们的界面中我们使用ProgressWheel实现后面三个效果(只写一个):

<com.todddavies.components.progressbar.ProgressWheel
    android:id="@+id/progressBarThree"
    android:layout_width="150dp"
    android:layout_height="150dp"
    ProgressWheel:text=""
    ProgressWheel:textColor="#222222"
    ProgressWheel:textSize="14sp"
    ProgressWheel:rimColor="#44000000"
    ProgressWheel:circleColor="#2E9121"
    ProgressWheel:barLength="20dp" 
    ProgressWheel:barColor="#8000"
    ProgressWheel:barWidth="25dp"
    ProgressWheel:rimWidth="25dp" 
    ProgressWheel:spinSpeed="-1dp" />
 其中的属性意思,我下面介绍一下,在value/attars.xml 中有定义:

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<declare-styleable name="ProgressWheel">
        <attr name="text" format="string" />
        <attr name="textColor" format="color" />
        <attr name="textSize" format="dimension" />
        <attr name="barColor" format="color" />
        <attr name="rimColor" format="color" />
        <attr name="rimWidth" format="dimension" />
        <attr name="spinSpeed" format="dimension" />
        <attr name="delayMillis" format="integer" />
        <attr name="circleColor" format="color" />
        <attr name="radius" format="dimension" />
        <attr name="barWidth" format="dimension" />
        <attr name="barLength" format="dimension" />
        <attr name="contourColor" format="color"/>
        <attr name="contourSize" format="dimension"/>
    </declare-styleable>   
</resources>

1.text、textColor、textSize为文字样式设置,位置见上图中的loading所示。

2.barColor、barWidth、barLength为外层的圈,也称bar,颜色、宽度、总共一圈分为多少等份,位置间上图中loading外的那一层。

3.rimColor、rimWidth是在bar上滑块滑动的颜色、宽度,这里没有长度,位置见上图中所示。

4.spinSpeed滑块滑动速度,delayMillis每次滑完一圈的延时,circleColor为progress中心颜色,radius为中心半径。

5.contourColor和ContourSize为bar的轮廓颜色、大小。

Java程序:

main.java程序为:

package com.todddavies.components.progressbar;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/**
 * A sample activity showing some of the functions of the progress bar 
 */
public class main extends Activity {
	boolean running;
	ProgressWheel pw_two;
	ProgressWheel pw_three;
	ProgressWheel pw_four;
	//ProgressWheel pw_five;
	int progress = 0;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progress_wheel_activity);
        pw_two = (ProgressWheel) findViewById(R.id.progressBarTwo);
        pw_three = (ProgressWheel) findViewById(R.id.progressBarThree);
        pw_four = (ProgressWheel) findViewById(R.id.progressBarFour);
        //pw_five = (ProgressWheel) findViewById(R.id.progressBarFive);
        
        int[] pixels = new int[] { 0xFF2E9121, 0xFF2E9121, 0xFF2E9121,
            0xFF2E9121, 0xFF2E9121, 0xFF2E9121, 0xFFFFFFFF, 0xFFFFFFFF};
        Bitmap bm = Bitmap.createBitmap(pixels, 8, 1, Bitmap.Config.ARGB_8888);
        Shader shader = new BitmapShader(bm,Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        pw_three.setRimShader(shader);
        
        pw_three.spin();
        pw_four.spin();
        pw_two.setText("Loading...");
		pw_two.spin();
        
        final Runnable r = new Runnable() {
			public void run() {
				running = true;
				while(progress<361) {
					pw_two.incrementProgress();
					progress++;
					try {
						Thread.sleep(15);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				running = false;
			}
        };
        
        Button spin = (Button) findViewById(R.id.btn_spin);
        spin.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(!running) {
					if(pw_two.isSpinning) {
						pw_two.stopSpinning();
					}
					pw_two.resetCount();
					pw_two.setText("Loading...");
					pw_two.spin();
				}
			}
        });
        
        Button increment = (Button) findViewById(R.id.btn_increment);
        increment.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(!running) {
					progress = 0;
					pw_two.resetCount();
					Thread s = new Thread(r);
					s.start();
				}
			}
        });
	}
	
	@Override
	public void onPause() {
		super.onPause();
		progress = 361;
		pw_two.stopSpinning();
		pw_two.resetCount();
		pw_two.setText("Click\none of the\nbuttons");
	}
}

看着很多,其实实际我们用的时候就用pw_two.spin,其他的是改变背景,如图所示的第三个图形,也还有就是显示加载百分比的效果,这里我没有贴图。

主要使用了ProgressWheel.java

源码地址:https://github.com/feiyangxiaomi/ProgressWheel/


以下是一个简单的自定义View实现K线图的代码示例: ``` public class KLineView extends View { private List<KLineData> mData; // K线数据 private int mWidth, mHeight; // 控件宽度、高度 private int mTopPadding; // 顶部留白 private int mBottomPadding; // 底部留白 private Paint mLinePaint; // K线画笔 private Paint mTextPaint; // 文本画笔 private float mMaxPrice, mMinPrice; // 最高价、最低价 private float mPriceScale; // 价格缩放比例 private float mVolumeScale; // 成交量缩放比例 private int mCandleWidth; // K线宽度 private int mCandleSpace; // K线间隔 public KLineView(Context context) { this(context, null); } public KLineView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public KLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 初始化画笔 mLinePaint = new Paint(); mLinePaint.setStrokeWidth(2f); mLinePaint.setAntiAlias(true); mLinePaint.setStyle(Paint.Style.STROKE); mTextPaint = new Paint(); mTextPaint.setTextSize(24f); mTextPaint.setAntiAlias(true); mTextPaint.setColor(Color.BLACK); // 初始化K线宽度、间隔 mCandleWidth = dp2px(8); mCandleSpace = dp2px(4); // 初始化留白 mTopPadding = dp2px(20); mBottomPadding = dp2px(20); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获取控件宽度、高度 mWidth = MeasureSpec.getSize(widthMeasureSpec); mHeight = MeasureSpec.getSize(heightMeasureSpec); // 计算价格、成交量缩放比例 mPriceScale = (mHeight - mTopPadding - mBottomPadding) / (mMaxPrice - mMinPrice); mVolumeScale = (mHeight - mTopPadding - mBottomPadding) / getMaxVolume(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制K线图 drawCandles(canvas); // 绘制边框 drawBorder(canvas); // 绘制Y轴标签 drawYLabels(canvas); } /** * 绘制K线图 */ private void drawCandles(Canvas canvas) { if (mData == null || mData.size() == 0) { return; } mLinePaint.setColor(Color.RED); mLinePaint.setStyle(Paint.Style.FILL); float startX = mCandleWidth / 2 + mCandleSpace; // 第一个K线起始X坐标 float startY = 0f; // K线起始Y坐标 float endX, endY; // K线结束X坐标、Y坐标 for (int i = 0; i < mData.size(); i++) { KLineData data = mData.get(i); // 计算K线顶部、底部Y坐标 float highY = mTopPadding + (mMaxPrice - data.getHigh()) * mPriceScale; float lowY = mTopPadding + (mMaxPrice - data.getLow()) * mPriceScale; // 计算K线开盘、收盘Y坐标 float openY = mTopPadding + (mMaxPrice - data.getOpen()) * mPriceScale; float closeY = mTopPadding + (mMaxPrice - data.getClose()) * mPriceScale; // 绘制K线实体 if (data.getOpen() < data.getClose()) { mLinePaint.setColor(Color.RED); } else { mLinePaint.setColor(Color.GREEN); } canvas.drawRect(startX - mCandleWidth / 2, closeY, startX + mCandleWidth / 2, openY, mLinePaint); // 绘制K线上下影线 mLinePaint.setColor(Color.BLACK); canvas.drawLine(startX, highY, startX, openY, mLinePaint); canvas.drawLine(startX, lowY, startX, closeY, mLinePaint); // 更新起始X坐标 startX += mCandleWidth + mCandleSpace; } } /** * 绘制边框 */ private void drawBorder(Canvas canvas) { mLinePaint.setColor(Color.BLACK); mLinePaint.setStyle(Paint.Style.STROKE); canvas.drawRect(0, 0, mWidth, mHeight, mLinePaint); } /** * 绘制Y轴标签 */ private void drawYLabels(Canvas canvas) { float labelHeight = mTextPaint.descent() - mTextPaint.ascent(); // 绘制价格标签 float priceLabelY = mTopPadding - mTextPaint.ascent(); for (float price = mMinPrice; price <= mMaxPrice; price += (mMaxPrice - mMinPrice) / 5) { float priceY = mTopPadding + (mMaxPrice - price) * mPriceScale; canvas.drawText(String.format(Locale.getDefault(), "%.2f", price), 0, priceY + labelHeight / 2, mTextPaint); canvas.drawLine(mCandleWidth / 2, priceY, mWidth, priceY, mLinePaint); } // 绘制成交量标签 float volumeLabelY = mHeight - mBottomPadding - mTextPaint.descent(); float maxVolume = getMaxVolume(); for (int i = 0; i < 5; i++) { float volumeY = volumeLabelY - i * labelHeight * maxVolume / 5; canvas.drawText(String.format(Locale.getDefault(), "%.0f", maxVolume * i / 5), 0, volumeY - labelHeight / 2, mTextPaint); } } /** * 设置K线数据 */ public void setData(List<KLineData> data) { mData = data; calculateMaxAndMinPrice(); requestLayout(); invalidate(); } /** * 计算最高价、最低价 */ private void calculateMaxAndMinPrice() { if (mData == null || mData.size() == 0) { return; } mMaxPrice = mData.get(0).getHigh(); mMinPrice = mData.get(0).getLow(); for (int i = 1; i < mData.size(); i++) { KLineData data = mData.get(i); mMaxPrice = Math.max(mMaxPrice, data.getHigh()); mMinPrice = Math.min(mMinPrice, data.getLow()); } } /** * 获取最大成交量 */ private float getMaxVolume() { float maxVolume = 0f; if (mData != null && mData.size() > 0) { for (KLineData data : mData) { maxVolume = Math.max(maxVolume, data.getVolume()); } } return maxVolume; } /** * dp转px */ private int dp2px(int dp) { return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); } } ``` 其中,KLineData表示K线数据,包括开盘价、收盘价、最高价、最低价、成交量等属性。可以根据实际需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值