<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android仿微博加載餅形圈

          共 11746字,需瀏覽 24分鐘

           ·

          2021-10-20 02:46

          之前寫過一個仿微博Loading加載的餅圖圈自定義View,一直放在磁盤里面,現(xiàn)在拿出來分享給有需要的小伙伴~


          完整代碼

          • 自定義屬性

                                                                                                  


          • Java代碼

          public class CircleAnnulusProgressBar extends View {    //-------------------- 默認(rèn)值 -------------------    /**     * 默認(rèn)的當(dāng)前進度,默認(rèn)為0     */    private static final int DEFAULT_PROGRESS = 0;    /**     * 默認(rèn)的最大值,默認(rèn)為100     */    private static final int DEFAULT_MAX = 100;    /**     * 默認(rèn)的外圓輪廓寬度,默認(rèn)是1dp     */    private static int DEFAULT_OUTER_CIRCLE_BORDER_WIDTH = 3;    /**     * 默認(rèn)的外圓的顏色     */    private final int DEFAULT_OUTER_CIRCLE_COLOR = Color.parseColor("#FFFFFF");    /**     * 默認(rèn)的內(nèi)餅形的顏色     */    private final int DEFAULT_PIE_CIRCLE = Color.parseColor("#FFFFFF");
          //-------------------- 自定義屬性 ------------------- /** * 默認(rèn)的外圓輪廓寬度,默認(rèn)是1dp */ private float mOuterCircleBorderWidth; /** * 外圓的顏色,默認(rèn)白色 */ private int mOuterCircleColor; /** * 內(nèi)餅圖填充的顏色,默認(rèn)是白色 */ private int mPieColor;
          //-------------------- 繪制相關(guān)對象 ------------------- /** * 外圓的畫筆 */ private Paint mOuterCirclePaint; /** * 內(nèi)部的餅形的畫筆 */ private Paint mPiePaint; /** * View繪制區(qū)域,去除了padding */ private RectF mRect;
          //-------------------- View寬高等參數(shù) ------------------- /** * View的寬,包括padding */ private int mWidth; /** * View的高,包括padding */ private int mHeight; /** * 設(shè)置的上下左右padding值 */ private int mPaddingTop; private int mPaddingBottom; private int mPaddingLeft; private int mPaddingRight; /** * 外圓的半徑,已經(jīng)處理了padding */ private float mRadius; /** * 當(dāng)前進度,默認(rèn)為最大值 */ private int mProgress; /** * 設(shè)置的最大進度,默認(rèn)為100 */ private int mMax;
          //-------------------- 對外使用的對象 ------------------- /** * 監(jiān)聽器集合 */ private ArrayList mListeners;
          public CircleAnnulusProgressBar(Context context) { super(context); init(null); }
          public CircleAnnulusProgressBar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(attrs); }
          public CircleAnnulusProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); }
          private void init(AttributeSet attrs) { //由于dp轉(zhuǎn)換操作必須在初始化后context才不為空,所以在這里初始化默認(rèn)的外圓輪廓寬度 DEFAULT_OUTER_CIRCLE_BORDER_WIDTH = dip2px(getContext(), 1f);
          //取出Xml設(shè)置的自定義屬性,當(dāng)前進度,最大進度 if (attrs != null) { TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.CircleAnnulusProgressBar); //Xml設(shè)置的進度 mProgress = array.getInt(R.styleable.CircleAnnulusProgressBar_progress, DEFAULT_PROGRESS); //Xml設(shè)置的最大值 mMax = array.getInt(R.styleable.CircleAnnulusProgressBar_max, DEFAULT_MAX); //Xml設(shè)置的外圓顏色,先讀取直接寫#FFFFFF等樣式的,如果沒有,則讀取使用引用方式的,就是@color/white這樣的 int resultOuterCircleColor = array.getColor(R.styleable.CircleAnnulusProgressBar_outer_circle_color, DEFAULT_OUTER_CIRCLE_COLOR); if (resultOuterCircleColor != DEFAULT_OUTER_CIRCLE_COLOR) { mOuterCircleColor = resultOuterCircleColor; } else { int outerCircleResId = array.getResourceId(R.styleable.CircleAnnulusProgressBar_outer_circle_color, android.R.color.white); mOuterCircleColor = getContext().getResources().getColor(outerCircleResId); } //Xml設(shè)置的內(nèi)餅圖顏色,同上,先讀取直接寫顏色值的,沒有再讀取使用引用方式的 int resultPieCircleColor = array.getColor(R.styleable.CircleAnnulusProgressBar_pie_color, DEFAULT_PIE_CIRCLE); if (resultPieCircleColor != DEFAULT_PIE_CIRCLE) { mPieColor = resultPieCircleColor; } else { int pieColorResId = array.getResourceId(R.styleable.CircleAnnulusProgressBar_pie_color, android.R.color.white); mPieColor = getContext().getResources().getColor(pieColorResId); } //讀取設(shè)置的外圓輪廓寬度,讀取dimension mOuterCircleBorderWidth = array.getDimensionPixelSize(R.styleable.CircleAnnulusProgressBar_outer_circle_border_width, DEFAULT_OUTER_CIRCLE_BORDER_WIDTH); //記得回收資源 array.recycle(); } else { //沒有在Xml中設(shè)置屬性,使用默認(rèn)屬性 //當(dāng)前進度 mProgress = DEFAULT_PROGRESS; //最大值 mMax = DEFAULT_MAX; //外圓的顏色 mOuterCircleColor = DEFAULT_OUTER_CIRCLE_COLOR; //內(nèi)餅形的顏色 mPieColor = DEFAULT_PIE_CIRCLE; //外圓的寬度 mOuterCircleBorderWidth = DEFAULT_OUTER_CIRCLE_BORDER_WIDTH; } //外層圓的畫筆 mOuterCirclePaint = new Paint(); mOuterCirclePaint.setColor(mOuterCircleColor); mOuterCirclePaint.setStyle(Paint.Style.STROKE); mOuterCirclePaint.setStrokeWidth(mOuterCircleBorderWidth); mOuterCirclePaint.setAntiAlias(true); //中間進度餅形畫筆 mPiePaint = new Paint(); mPiePaint.setColor(mPieColor); mPiePaint.setStyle(Paint.Style.FILL); mPiePaint.setAntiAlias(true); }
          @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //取出總寬高 mWidth = w; mHeight = h; //取出設(shè)置的padding值 mPaddingTop = getPaddingTop(); mPaddingBottom = getPaddingBottom(); mPaddingLeft = getPaddingLeft(); mPaddingRight = getPaddingRight(); //計算外圓直徑,取寬高中最小的為圓的直徑,這里要處理添加padding的情況。 float diameter = (Math.min(mWidth, mHeight)) - mPaddingLeft - mPaddingRight; //直徑除以2算出半徑 mRadius = (float) ((diameter / 2) * 0.98);
          //建立一個Rect保存View的范圍,后面畫餅形也需要用到 mRect = new RectF(mPaddingLeft, mPaddingTop, mWidth - mPaddingRight, mHeight - mPaddingBottom); }
          @Override protected void onFinishInflate() { super.onFinishInflate(); setBackgroundColor(getContext().getResources().getColor(android.R.color.transparent)); }
          @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //取出寬的模式和大小 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); //取出高的模式和大小 int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec);
          //設(shè)置的寬高不相等時,將寬高都進行校正,取最小的為標(biāo)準(zhǔn) if (widthSize != heightSize) { int finalSize = Math.min(widthSize, heightSize); widthSize = finalSize; heightSize = finalSize; }
          //默認(rèn)寬高值 int defaultWidth = dip2px(getContext(), 55); int defaultHeight = dip2px(getContext(), 55);
          if (widthMode != MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) { //當(dāng)寬高都設(shè)置wrapContent時設(shè)置我們的默認(rèn)值 if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) { setMeasuredDimension(defaultWidth, defaultHeight); } else if (widthMode == MeasureSpec.AT_MOST) { //寬、高任意一個為wrapContent都設(shè)置我們默認(rèn)值 setMeasuredDimension(defaultWidth, heightSize); } else if (heightMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSize, defaultHeight); } } else { setMeasuredDimension(widthSize, heightSize); } }
          @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //獲取當(dāng)前的進度 int curProgress = getProgress(); //越界處理 if (curProgress < 0) { curProgress = 0; } if (curProgress > mMax) { curProgress = mMax; } //畫外圓,這里使用寬和高都可以,因為我們限定寬和高都是相等的 //這里圓心坐標(biāo)一直都在View的寬高的中間,就算有padding都是不會變的,變的只是半徑,半徑初始化前已經(jīng)去處理了padding,這里要注意 canvas.drawCircle(mWidth / 2, mWidth / 2, mRadius, mOuterCirclePaint); //要進行畫布縮放操作,先保存圖層,因為縮放、平移等操作是疊加的,所以使用完必須恢復(fù),否則下次的onDraw就會累加縮放 canvas.save(); //用縮放畫布,進行縮放中心的餅圖,設(shè)置縮放中心是控件的中心 canvas.scale(0.90f, 0.90f, mWidth / 2, mHeight / 2); //計算當(dāng)前進度對應(yīng)的角度 float angle = 360 * (curProgress * 1.0f / getMax()); //畫餅圖,-90度就是12點方向開始 canvas.drawArc(mRect, -90, angle, true, mPiePaint); //還原畫布圖層 canvas.restore(); //回調(diào)進度給外面的監(jiān)聽器 for (OnProgressUpdateListener listener : mListeners) { listener.onProgressUpdate(curProgress); } }
          /** * 設(shè)置進度 * * @param progress 要設(shè)置的進度 */ public synchronized void setProgress(int progress) { if (progress < 0) { progress = 0; } this.mProgress = progress; //設(shè)置進度可能是子線程,所以將重繪調(diào)用交給主線程 postInvalidate(); }
          /** * 獲取當(dāng)前進度 * * @return 當(dāng)前的進度 */ public int getProgress() { return mProgress; }
          /** * 設(shè)置最大值 * * @param max 要設(shè)置的最大值 */ public synchronized void setMax(int max) { if (max < 0) { max = 0; } this.mMax = max; //設(shè)置進度可能是子線程,所以將重繪調(diào)用交給主線程 postInvalidate(); }
          /** * 進度更新的回調(diào)監(jiān)聽 */ public interface OnProgressUpdateListener { //當(dāng)進度更新時回調(diào) void onProgressUpdate(int progress); }
          /** * 設(shè)置更新回調(diào) * * @param listener 監(jiān)聽器實例 */ public void addOnProgressUpdateListener(OnProgressUpdateListener listener) { if (mListeners == null) { mListeners = new ArrayList(); } this.mListeners.add(listener); }
          /** * 獲取設(shè)置的最大值 * * @return 設(shè)置的最大值 */ public int getMax() { return mMax; }
          //------------------ 一些尺寸轉(zhuǎn)換方法 ------------------ public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); }
          public static int px2dp(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); }
          private int sp2px(Context context, float spVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, context.getResources().getDisplayMetrics()); }}


          示例代碼

          • Xml布局

              xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#66000000">
          android:id="@+id/tipText" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="15dp" android:text="當(dāng)前進度:" android:textColor="#FFFFFF" android:textSize="14sp" />
          android:id="@+id/progressBar" android:layout_width="55dp" android:layout_height="55dp" android:layout_centerInParent="true" app:max="100" app:outer_circle_border_width="1dp" app:outer_circle_color="#FFFFFF" app:pie_color="@android:color/white" app:progress="30" />


          • Java代碼

          public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);
          //餅圖控件 final CircleAnnulusProgressBar progressBar = findViewById(R.id.progressBar); //提示問題 final TextView tipText = findViewById(R.id.tipText); //設(shè)置進度最大值 progressBar.setMax(100); //設(shè)置進度更新監(jiān)聽,每次更新時重新設(shè)置提示文字 progressBar.addOnProgressUpdateListener(new CircleAnnulusProgressBar.OnProgressUpdateListener() { @Override public void onProgressUpdate(int progress) { tipText.setText("當(dāng)前進度: ".concat(String.valueOf(progress))); } }); //用值動畫不斷改變進度,測試進度 ValueAnimator animator = ValueAnimator.ofInt(0, 100); animator.setRepeatMode(ValueAnimator.RESTART); animator.setRepeatCount(ValueAnimator.INFINITE); animator.setInterpolator(new LinearInterpolator()); animator.setDuration(3000); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Integer cValue = (Integer) animation.getAnimatedValue(); progressBar.setProgress(cValue); } }); animator.start(); }}


          到這里就結(jié)束啦。
          瀏覽 11
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www操操操 | 婷婷伊人綜合中文字幕小说 | 久久久免费黄色 | 爱搞在线国产 | 久久久久福利视频 |