Android_自定义进度条

简介: 转载:http://blog.csdn.net/lmj623565791/article/details/43371299 ,本文出自:【张鸿洋的博客】 1、概述 最近需要用进度条,秉着不重复造轮子的原则,上github上搜索了一番,看了几个觉得比较好看的ProgressBar,比如:daimajia的等。

转载:http://blog.csdn.net/lmj623565791/article/details/43371299 ,本文出自:【张鸿洋的博客】

1、概述

最近需要用进度条,秉着不重复造轮子的原则,上github上搜索了一番,看了几个觉得比较好看的ProgressBar,比如:daimajia的等。简单看了下代码,基本都是继承自View,彻彻底底的自定义了一个进度条。盯着那绚丽滚动条,忽然觉得,为什么要通过View去写一个滚动条,系统已经提供了ProgressBar以及属于它的特性,我们没必要重新去构建一个,但是系统的又比较丑,不同版本变现还不一定一样。那么得出我们的目标:改变系统ProgressBar的样子。 

  对没错,我们没有必要去从0打造一个ProgressBar,人家虽然长的不好看,但是特性以及稳定性还是刚刚的,我们只需要为其整下容就ok了。 

说到整容,大家都知道我们的控件是通过onDraw()画出来的,那么我们只需要去覆盖它的onDraw()方法,自己写下就ok 。 

对了,我创建了一个微信公众号,欢迎关注,左边栏目上扫一扫即可。

  接下来,我们贴下效果图:

2、效果图

1、横向的进度条

 

2、圆形的进度条

没错,这就是我们的进度条效果,横向的模仿了daimajia的进度条样子。不过我们继承子ProgressBar,简单的为其整个容,代码清晰易懂 。为什么说,易懂呢?

横向那个进度条,大家会drawLine()和drawText()吧,那么通过getWidth()拿到控件的宽度,再通过getProgress()拿到进度,按比例控制绘制线的长短,字的位置还不是分分钟的事。

github源码地址Android-ProgressBarWidthNumber欢迎大家star or fork 。

 

3、实现

横向的滚动条绘制肯定需要一些属性,比如已/未到达进度的颜色、宽度,文本的颜色、大小等。 
本来呢,我是想通过系统ProgressBar的progressDrawable,从里面提取一些属性完成绘制需要的参数的。但是,最终呢,反而让代码变得复杂。所以最终还是改用自定义属性。 说道自定义属性,大家应该已经不陌生了。

1、HorizontalProgressBarWithNumber

1、自定义属性

values/attr_progress_bar.xml:

 

[html]  view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <declare-styleable name="HorizontalProgressBarWithNumber">  
  5.         <attr name="progress_unreached_color" format="color" />  
  6.         <attr name="progress_reached_color" format="color" />  
  7.         <attr name="progress_reached_bar_height" format="dimension" />  
  8.         <attr name="progress_unreached_bar_height" format="dimension" />  
  9.         <attr name="progress_text_size" format="dimension" />  
  10.         <attr name="progress_text_color" format="color" />  
  11.         <attr name="progress_text_offset" format="dimension" />  
  12.         <attr name="progress_text_visibility" format="enum">  
  13.             <enum name="visible" value="0" />  
  14.             <enum name="invisible" value="1" />  
  15.         </attr>  
  16.     </declare-styleable>  
  17.       
  18.     <declare-styleable name="RoundProgressBarWidthNumber">  
  19.         <attr name="radius" format="dimension" />  
  20.     </declare-styleable>  
  21.   
  22. </resources>  

 

2、构造中获取

 

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. public class HorizontalProgressBarWithNumber extends ProgressBar  
  2. {  
  3.   
  4.     private static final int DEFAULT_TEXT_SIZE = 10;  
  5.     private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;  
  6.     private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da;  
  7.     private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2;  
  8.     private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;  
  9.     private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;  
  10.   
  11.     /** 
  12.      * painter of all drawing things 
  13.      */  
  14.     protected Paint mPaint = new Paint();  
  15.     /** 
  16.      * color of progress number 
  17.      */  
  18.     protected int mTextColor = DEFAULT_TEXT_COLOR;  
  19.     /** 
  20.      * size of text (sp) 
  21.      */  
  22.     protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);  
  23.   
  24.     /** 
  25.      * offset of draw progress 
  26.      */  
  27.     protected int mTextOffset = dp2px(DEFAULT_SIZE_TEXT_OFFSET);  
  28.   
  29.     /** 
  30.      * height of reached progress bar 
  31.      */  
  32.     protected int mReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR);  
  33.   
  34.     /** 
  35.      * color of reached bar 
  36.      */  
  37.     protected int mReachedBarColor = DEFAULT_TEXT_COLOR;  
  38.     /** 
  39.      * color of unreached bar 
  40.      */  
  41.     protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;  
  42.     /** 
  43.      * height of unreached progress bar 
  44.      */  
  45.     protected int mUnReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR);  
  46.     /** 
  47.      * view width except padding 
  48.      */  
  49.     protected int mRealWidth;  
  50.       
  51.     protected boolean mIfDrawText = true;  
  52.   
  53.     protected static final int VISIBLE = 0;  
  54.   
  55.     public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs)  
  56.     {  
  57.         this(context, attrs, 0);  
  58.     }  
  59.   
  60.     public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs,  
  61.             int defStyle)  
  62.     {  
  63.         super(context, attrs, defStyle);  
  64.           
  65.         setHorizontalScrollBarEnabled(true);  
  66.   
  67.         obtainStyledAttributes(attrs);  
  68.   
  69.         mPaint.setTextSize(mTextSize);  
  70.         mPaint.setColor(mTextColor);  
  71.   
  72.     }  
  73.       
  74.     /** 
  75.      * get the styled attributes 
  76.      *  
  77.      * @param attrs 
  78.      */  
  79.     private void obtainStyledAttributes(AttributeSet attrs)  
  80.     {  
  81.         // init values from custom attributes  
  82.         final TypedArray attributes = getContext().obtainStyledAttributes(  
  83.                 attrs, R.styleable.HorizontalProgressBarWithNumber);  
  84.   
  85.         mTextColor = attributes  
  86.                 .getColor(  
  87.                         R.styleable.HorizontalProgressBarWithNumber_progress_text_color,  
  88.                         DEFAULT_TEXT_COLOR);  
  89.         mTextSize = (int) attributes.getDimension(  
  90.                 R.styleable.HorizontalProgressBarWithNumber_progress_text_size,  
  91.                 mTextSize);  
  92.   
  93.         mReachedBarColor = attributes  
  94.                 .getColor(  
  95.                         R.styleable.HorizontalProgressBarWithNumber_progress_reached_color,  
  96.                         mTextColor);  
  97.         mUnReachedBarColor = attributes  
  98.                 .getColor(  
  99.                         R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,  
  100.                         DEFAULT_COLOR_UNREACHED_COLOR);  
  101.         mReachedProgressBarHeight = (int) attributes  
  102.                 .getDimension(  
  103.                         R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,  
  104.                         mReachedProgressBarHeight);  
  105.         mUnReachedProgressBarHeight = (int) attributes  
  106.                 .getDimension(  
  107.                         R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,  
  108.                         mUnReachedProgressBarHeight);  
  109.         mTextOffset = (int) attributes  
  110.                 .getDimension(  
  111.                         R.styleable.HorizontalProgressBarWithNumber_progress_text_offset,  
  112.                         mTextOffset);  
  113.   
  114.         int textVisible = attributes  
  115.                 .getInt(R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility,  
  116.                         VISIBLE);  
  117.         if (textVisible != VISIBLE)  
  118.         {  
  119.             mIfDrawText = false;  
  120.         }  
  121.         attributes.recycle();  
  122.     }  


嗯,看起来代码挺长,其实都是在获取自定义属性,没什么技术含量。

 

 

3、onMeasure

刚才不是出onDraw里面写写就行了么,为什么要改onMeasure呢,主要是因为我们所有的属性比如进度条宽度让用户自定义了,所以我们的测量也得稍微变下。

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. @Override  
  2. protected synchronized void onMeasure(int widthMeasureSpec,  
  3.         int heightMeasureSpec)  
  4. {  
  5.     int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  6.   
  7.     if (heightMode != MeasureSpec.EXACTLY)  
  8.     {  
  9.   
  10.         float textHeight = (mPaint.descent() + mPaint.ascent());  
  11.         int exceptHeight = (int) (getPaddingTop() + getPaddingBottom() + Math  
  12.                 .max(Math.max(mReachedProgressBarHeight,  
  13.                         mUnReachedProgressBarHeight), Math.abs(textHeight)));  
  14.   
  15.         heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight,  
  16.                 MeasureSpec.EXACTLY);  
  17.     }  
  18.     super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  19.   
  20. }  


宽度我们不变,所以的自定义属性不涉及宽度,高度呢,只考虑不是EXACTLY的情况(用户明确指定了,我们就不管了),根据padding和进度条宽度算出自己想要的,如果非EXACTLY下,我们进行exceptHeight封装,传入给控件进行测量高度。

 

测量完,就到我们的onDraw了~~~

4、onDraw

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. @Override  
  2.     protected synchronized void onDraw(Canvas canvas)  
  3.     {  
  4.         canvas.save();  
  5.         //画笔平移到指定paddingLeft, getHeight() / 2位置,注意以后坐标都为以此为0,0  
  6.         canvas.translate(getPaddingLeft(), getHeight() / 2);  
  7.   
  8.         boolean noNeedBg = false;  
  9.         //当前进度和总值的比例  
  10.         float radio = getProgress() * 1.0f / getMax();  
  11.         //已到达的宽度  
  12.         float progressPosX = (int) (mRealWidth * radio);  
  13.         //绘制的文本  
  14.         String text = getProgress() + "%";  
  15.   
  16.         //拿到字体的宽度和高度  
  17.         float textWidth = mPaint.measureText(text);  
  18.         float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;  
  19.   
  20.         //如果到达最后,则未到达的进度条不需要绘制  
  21.         if (progressPosX + textWidth > mRealWidth)  
  22.         {  
  23.             progressPosX = mRealWidth - textWidth;  
  24.             noNeedBg = true;  
  25.         }  
  26.   
  27.         // 绘制已到达的进度  
  28.         float endX = progressPosX - mTextOffset / 2;  
  29.         if (endX > 0)  
  30.         {  
  31.             mPaint.setColor(mReachedBarColor);  
  32.             mPaint.setStrokeWidth(mReachedProgressBarHeight);  
  33.             canvas.drawLine(0, 0, endX, 0, mPaint);  
  34.         }  
  35.       
  36.         // 绘制文本  
  37.         if (mIfDrawText)  
  38.         {  
  39.             mPaint.setColor(mTextColor);  
  40.             canvas.drawText(text, progressPosX, -textHeight, mPaint);  
  41.         }  
  42.   
  43.         // 绘制未到达的进度条  
  44.         if (!noNeedBg)  
  45.         {  
  46.             float start = progressPosX + mTextOffset / 2 + textWidth;  
  47.             mPaint.setColor(mUnReachedBarColor);  
  48.             mPaint.setStrokeWidth(mUnReachedProgressBarHeight);  
  49.             canvas.drawLine(start, 0, mRealWidth, 0, mPaint);  
  50.         }  
  51.   
  52.         canvas.restore();  
  53.   
  54.     }  
  55.   
  56.     @Override  
  57.     protected void onSizeChanged(int w, int h, int oldw, int oldh)  
  58.     {  
  59.         super.onSizeChanged(w, h, oldw, oldh);  
  60.         mRealWidth = w - getPaddingRight() - getPaddingLeft();  
  61.   
  62.     }  

 

 

其实核心方法就是onDraw了,但是呢,onDraw也很简单,绘制线、绘制文本、绘制线,结束。

 

还有两个简单的辅助方法:

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. /** 
  2.  * dp 2 px 
  3.  *  
  4.  * @param dpVal 
  5.  */  
  6. protected int dp2px(int dpVal)  
  7. {  
  8.     return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  
  9.             dpVal, getResources().getDisplayMetrics());  
  10. }  
  11.   
  12. /** 
  13.  * sp 2 px 
  14.  *  
  15.  * @param spVal 
  16.  * @return 
  17.  */  
  18. protected int sp2px(int spVal)  
  19. {  
  20.     return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,  
  21.             spVal, getResources().getDisplayMetrics());  
  22.   
  23. }  

 

 

好了,到此我们的横向进度就结束了,是不是很简单~~如果你是自定义View,你还得考虑progress的更新,考虑状态的销毁与恢复等等复杂的东西。

接下来看我们的RoundProgressBarWidthNumber圆形的进度条。

2、RoundProgressBarWidthNumber 

圆形的进度条和横向的进度条基本变量都是一致的,于是我就让RoundProgressBarWidthNumber extends HorizontalProgressBarWithNumber 了。

然后需要改变的就是测量和onDraw了:

完整代码:

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. package com.zhy.view;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Paint.Cap;  
  7. import android.graphics.Paint.Style;  
  8. import android.graphics.RectF;  
  9. import android.util.AttributeSet;  
  10.   
  11. import com.zhy.library.view.R;  
  12.   
  13. public class RoundProgressBarWidthNumber extends  
  14.         HorizontalProgressBarWithNumber {  
  15.     /** 
  16.      * mRadius of view 
  17.      */  
  18.     private int mRadius = dp2px(30);  
  19.   
  20.     public RoundProgressBarWidthNumber(Context context) {  
  21.         this(context, null);  
  22.     }  
  23.   
  24.     public RoundProgressBarWidthNumber(Context context, AttributeSet attrs) {  
  25.         super(context, attrs);  
  26.   
  27.         mReachedProgressBarHeight = (int) (mUnReachedProgressBarHeight * 2.5f);  
  28.         TypedArray ta = context.obtainStyledAttributes(attrs,  
  29.                 R.styleable.RoundProgressBarWidthNumber);  
  30.         mRadius = (int) ta.getDimension(  
  31.                 R.styleable.RoundProgressBarWidthNumber_radius, mRadius);  
  32.         ta.recycle();  
  33.   
  34.         mTextSize = sp2px(14);  
  35.   
  36.         mPaint.setStyle(Style.STROKE);  
  37.         mPaint.setAntiAlias(true);  
  38.         mPaint.setDither(true);  
  39.         mPaint.setStrokeCap(Cap.ROUND);  
  40.   
  41.     }  
  42.   
  43.     @Override  
  44.     protected synchronized void onMeasure(int widthMeasureSpec,  
  45.             int heightMeasureSpec) {  
  46.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  47.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  48.   
  49.         int paintWidth = Math.max(mReachedProgressBarHeight,  
  50.                 mUnReachedProgressBarHeight);  
  51.   
  52.         if (heightMode != MeasureSpec.EXACTLY) {  
  53.   
  54.             int exceptHeight = (int) (getPaddingTop() + getPaddingBottom()  
  55.                     + mRadius * 2 + paintWidth);  
  56.             heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight,  
  57.                     MeasureSpec.EXACTLY);  
  58.         }  
  59.         if (widthMode != MeasureSpec.EXACTLY) {  
  60.             int exceptWidth = (int) (getPaddingLeft() + getPaddingRight()  
  61.                     + mRadius * 2 + paintWidth);  
  62.             widthMeasureSpec = MeasureSpec.makeMeasureSpec(exceptWidth,  
  63.                     MeasureSpec.EXACTLY);  
  64.         }  
  65.   
  66.         super.onMeasure(heightMeasureSpec, heightMeasureSpec);  
  67.   
  68.     }  
  69.   
  70.     @Override  
  71.     protected synchronized void onDraw(Canvas canvas) {  
  72.   
  73.         String text = getProgress() + "%";  
  74.         // mPaint.getTextBounds(text, 0, text.length(), mTextBound);  
  75.         float textWidth = mPaint.measureText(text);  
  76.         float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;  
  77.   
  78.         canvas.save();  
  79.         canvas.translate(getPaddingLeft(), getPaddingTop());  
  80.         mPaint.setStyle(Style.STROKE);  
  81.         // draw unreaded bar  
  82.         mPaint.setColor(mUnReachedBarColor);  
  83.         mPaint.setStrokeWidth(mUnReachedProgressBarHeight);  
  84.         canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);  
  85.         // draw reached bar  
  86.         mPaint.setColor(mReachedBarColor);  
  87.         mPaint.setStrokeWidth(mReachedProgressBarHeight);  
  88.         float sweepAngle = getProgress() * 1.0f / getMax() * 360;  
  89.         canvas.drawArc(new RectF(0, 0, mRadius * 2, mRadius * 2), 0,  
  90.                 sweepAngle, false, mPaint);  
  91.         // draw text  
  92.         mPaint.setStyle(Style.FILL);  
  93.         canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight,  
  94.                 mPaint);  
  95.   
  96.         canvas.restore();  
  97.   
  98.     }  
  99.   
  100. }  


首先获取它的专有属性mRadius,然后根据此属性去测量,测量完成绘制;

 

绘制的过程呢?

先绘制一个细一点的圆,然后绘制一个粗一点的弧度,二者叠在一起就行。文本呢,绘制在中间~~~总体,没什么代码量。

好了,两个进度条就到这了,是不是发现简单很多。总体设计上,存在些问题,如果抽取一个BaseProgressBar用于获取公共的属性;然后不同样子的进度条继承分别实现自己的测量和样子,这样结构可能会清晰些~~~

 

4、使用

布局文件

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:zhy="http://schemas.android.com/apk/res-auto"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.   
  7.     <LinearLayout  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:orientation="vertical"  
  11.         android:padding="25dp" >  
  12.   
  13.         <com.zhy.view.HorizontalProgressBarWithNumber  
  14.             android:id="@+id/id_progressbar01"  
  15.             android:layout_width="match_parent"  
  16.             android:layout_height="wrap_content"  
  17.             android:layout_marginTop="50dip"  
  18.             android:padding="5dp" />  
  19.   
  20.          
  21.   
  22.         <com.zhy.view.HorizontalProgressBarWithNumber  
  23.             android:layout_width="match_parent"  
  24.             android:layout_height="wrap_content"  
  25.             android:layout_marginTop="50dip"  
  26.             android:padding="5dp"  
  27.             android:progress="50"  
  28.             zhy:progress_text_color="#ffF53B03"  
  29.             zhy:progress_unreached_color="#ffF7C6B7" />  
  30.   
  31.         <com.zhy.view.RoundProgressBarWidthNumber  
  32.             android:id="@+id/id_progress02"  
  33.             android:layout_width="match_parent"  
  34.             android:layout_height="wrap_content"  
  35.             android:layout_marginTop="50dip"  
  36.             android:padding="5dp"  
  37.             android:progress="30" />  
  38.   
  39.         <com.zhy.view.RoundProgressBarWidthNumber  
  40.             android:layout_width="match_parent"  
  41.             android:layout_height="wrap_content"  
  42.             android:layout_marginTop="50dip"  
  43.             android:padding="5dp"  
  44.             android:progress="50"  
  45.             zhy:progress_reached_bar_height="20dp"  
  46.             zhy:progress_text_color="#ffF53B03"  
  47.             zhy:radius="60dp" />  
  48.        
  49.     </LinearLayout>  
  50.   
  51. </ScrollView>  

MainActivity

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. package com.zhy.sample.progressbar;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6.   
  7. import com.zhy.annotation.Log;  
  8. import com.zhy.view.HorizontalProgressBarWithNumber;  
  9.   
  10. public class MainActivity extends Activity {  
  11.   
  12.     private HorizontalProgressBarWithNumber mProgressBar;  
  13.     private static final int MSG_PROGRESS_UPDATE = 0x110;  
  14.   
  15.     private Handler mHandler = new Handler() {  
  16.         @Log  
  17.         public void handleMessage(android.os.Message msg) {  
  18.             int progress = mProgressBar.getProgress();  
  19.             mProgressBar.setProgress(++progress);  
  20.             if (progress >= 100) {  
  21.                 mHandler.removeMessages(MSG_PROGRESS_UPDATE);  
  22.                   
  23.             }  
  24.             mHandler.sendEmptyMessageDelayed(MSG_PROGRESS_UPDATE, 100);  
  25.         };  
  26.     };  
  27.   
  28.     @Log  
  29.     @Override  
  30.     protected void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.activity_main);  
  33.         mProgressBar = (HorizontalProgressBarWithNumber) findViewById(R.id.id_progressbar01);  
  34.         mHandler.sendEmptyMessage(MSG_PROGRESS_UPDATE);  
  35.   
  36.     }  
  37.   
  38. }  

最后,本篇博客的目的呢?就是为了说下,类似ProgressBar这样的控件,如果你只是想去改变显示的样子,完全没必要从0去创建,复写onDraw即可,当然是个人观点,提出供大家参考。

 

源码点击下载  

目录
相关文章
|
4月前
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
402 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
4月前
|
Android开发
Android自定义view之利用PathEffect实现动态效果
本文介绍如何在Android自定义View中利用`PathEffect`实现动态效果。通过改变偏移量,结合`PathEffect`的子类(如`CornerPathEffect`、`DashPathEffect`、`PathDashPathEffect`等)实现路径绘制的动态变化。文章详细解析了各子类的功能与参数,并通过案例代码展示了如何使用`ComposePathEffect`组合效果,以及通过修改偏移量实现动画。最终效果为一个菱形图案沿路径运动,源码附于文末供参考。
|
4月前
|
Android开发 开发者
Android自定义view之利用drawArc方法实现动态效果
本文介绍了如何通过Android自定义View实现动态效果,重点使用`drawArc`方法完成圆弧动画。首先通过`onSizeChanged`进行测量,初始化画笔属性,设置圆弧相关参数。核心思路是不断改变圆弧扫过角度`sweepAngle`,并调用`invalidate()`刷新View以实现动态旋转效果。最后附上完整代码与效果图,帮助开发者快速理解并实践这一动画实现方式。
129 0
|
4月前
|
Android开发 数据安全/隐私保护 开发者
Android自定义view之模仿登录界面文本输入框(华为云APP)
本文介绍了一款自定义输入框的实现,包含静态效果、hint值浮动动画及功能扩展。通过组合多个控件完成界面布局,使用TranslateAnimation与AlphaAnimation实现hint文字上下浮动效果,支持密码加密解密显示、去除键盘回车空格输入、光标定位等功能。代码基于Android平台,提供完整源码与attrs配置,方便复用与定制。希望对开发者有所帮助。
|
4月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
208 65
Android自定义view之网易云推荐歌单界面
|
4月前
|
XML 前端开发 Android开发
一篇文章带你走近Android自定义view
这是一篇关于Android自定义View的全面教程,涵盖从基础到进阶的知识点。文章首先讲解了自定义View的必要性及简单实现(如通过三个构造函数解决焦点问题),接着深入探讨Canvas绘图、自定义属性设置、动画实现等内容。还提供了具体案例,如跑马灯、折线图、太极图等。此外,文章详细解析了View绘制流程(measure、layout、draw)和事件分发机制。最后延伸至SurfaceView、GLSurfaceView、SVG动画等高级主题,并附带GitHub案例供实践。适合希望深入理解Android自定义View的开发者学习参考。
505 84
|
4月前
|
Android开发 开发者
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
本文详细介绍了如何通过自定义 `attrs.xml` 文件实现 Android 自定义 View 的属性配置。以一个包含 TextView 和 ImageView 的 DemoView 为例,讲解了如何使用自定义属性动态改变文字内容和控制图片显示隐藏。同时,通过设置布尔值和点击事件,实现了图片状态的切换功能。代码中展示了如何在构造函数中解析自定义属性,并通过方法 `setSetting0n` 和 `setbackeguang` 实现功能逻辑的优化与封装。此示例帮助开发者更好地理解自定义 View 的开发流程与 attrs.xml 的实际应用。
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
|
4月前
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
102 3
|
4月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
257 2
|
4月前
|
Android开发 开发者
Android自定义view之围棋动画(化繁为简)
本文介绍了Android自定义View的动画实现,通过两个案例拓展动态效果。第一个案例基于`drawArc`方法实现单次动画,借助布尔值控制动画流程。第二个案例以围棋动画为例,从简单的小球直线运动到双向变速运动,最终实现循环动画效果。代码结构清晰,逻辑简明,展示了如何化繁为简实现复杂动画,帮助读者拓展动态效果设计思路。文末提供完整源码,适合初学者和进阶开发者学习参考。
Android自定义view之围棋动画(化繁为简)