Android自定义控件系列案例【四】
案例效果:
模拟器上运行有些锯齿,真机上和预期一样好
案例分析:
看效果,第一直觉肯定是Android原生态控件中没有这样的控件实现这种效果,自然想到应该需要自定义控件了,没错,这就是通过自定义控件来绘制的一个圆环进度条。仔细分析发现这个效果的进度条应该由几个部分组成,首先是无进度时的浅色圆环,然后是一个随进度变化的深色圆弧,而中间部分是一个深蓝色的实心圆,最后就是显示进度百分比的文字。这几部分大部分都是图形,所以使用图形绘制技术应该可以绘制出分部分效果,然后加上进度控制部分应该心里就有底了。
技术实现:
按照上面的分析我们一部分一部分的来实现。先大概列一个步骤: (1)自定义View,重写构造方法,重写onDraw()方法。重写onDraw()方法的目的是为了找到绘制图形的时机与场所。(2)绘制浅色圆环。
需求准备Paint画笔,并设置画笔宽度,颜色,样式等,然后绘制圆环。(3)绘制深色进度圆弧。
重置Paint画笔,并设置画笔颜色,绘制进度圆弧。(4)添加SeekBar,并通过进度变化控制进度圆弧。
测试进度圆弧是否会随进度的变化正常工作。(5)绘制深蓝色实心圆。
重置Paint画笔,并设置画笔颜色,绘制实心圆。(6)绘制百分比文本。
计算进度百分比,绘制文本。(7)自定义属性,使进度条样式可配置(扩展部分)。
- 自定义View,重写构造方法,重写onDraw()方法
package com.kedi.myprogressbar;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.View;public class MyProgressBar extends View {public MyProgressBar(Context context) {this(context, null);}public MyProgressBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}}有了自定义MyProgressBar,此时就可以在XML布局中先占位了,下面是XML布局文件。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.kedi.myprogressbar.MyProgressBar android:id="@+id/pg" android:layout_width="120dp" android:layout_height="120dp" android:padding="5dp" android:layout_centerInParent="true" > </com.kedi.myprogressbar.MyProgressBar> <SeekBar android:id="@+id/sb" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/pg" android:max="100" android:layout_margin="20dp" /></RelativeLayout>
- 绘制浅色圆环
Paint 画笔:
|- new Paint() 创建画笔|-setColor() 设置画笔颜色|-setStyle()设置画笔样式(Paint.Style.STROKE 虚框样式,Paint.Style.FILL 实心样式)|-setStrokeWidth()设置画笔线宽|-setAntiAlias()消除锯齿或毛边|-setTextSize()设置画文本时的文本大小|-setTypeface()设置画文本时的文本字体
Canvas画布:
|-drawCircle(cx, cy, radius, paint)绘制圆环或圆。cx,cy:圆心坐标,radius:圆半径,paint:画笔。|-drawText(text, x, y, paint)绘制文本。text:文本,x,y:文本坐标,paint:画笔。|-drawArc(oval, startAngle, sweepAngle, useCenter, paint)绘制圆弧。oval:矩形区域,用来确定圆弧形状和大小。new RectF(left, top, right, bottom)确定一个矩形区域。startAngle:圆弧始端角度。sweepAngle:圆弧末端角度。paint:画笔。userCenter:设置是否显示圆弧的两边线条,false时只画圆弧没有两边,true时带两边。如下图:
有了这些技术准备,绘制工作将一路顺利。为了进行接下来的绘制工作,先在初始化方法中创建一个空画笔。
public class MyProgressBar extends View {private Paint paint;// 画笔public MyProgressBar(Context context) {this(context, null);}public MyProgressBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init();}/** * 初始化方法 */private void init() { paint = new Paint();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}}接下来绘制浅色圆环 核心逻辑:
private int roundW;// 圆环宽/** * 初始化方法 */private void init() { paint = new Paint(); //初始化圆环宽,这里考虑了适配把15dp进行了对应平台的像素转换。 roundW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics());} // 1.圆心(x,y)坐标值int centerX = getWidth() / 2;int centerY = centerX;// 2.圆环半径int radius1 = (centerX - roundW / 2);// 3.设置圆环颜色(浅色)paint.setColor(Color.parseColor("#11339ED4"));// 4.设置画笔的风格paint.setStyle(Paint.Style.STROKE);// 5.设置画圆环的宽度paint.setStrokeWidth(roundW);// 6.消除锯齿paint.setAntiAlias(true);// 7.画圆环canvas.drawCircle(centerX, centerY, radius1, paint);完整代码(如何是直接拷贝这块代码的时候记的修改包名和导包):
package com.kedi.myprogressbar;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;public class MyProgressBar extends View {private Paint paint;// 画笔private int roundW;// 圆环宽public MyProgressBar(Context context) {this(context, null);}public MyProgressBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}/** * 初始化方法 */private void init() {paint = new Paint();// 初始化圆环宽,这里考虑了适配把15dp进行了对应平台的像素转换。roundW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics());}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制浅色圆环// 1.圆心(x,y)坐标值int centerX = getWidth() / 2;int centerY = centerX;// 2.圆环半径int radius1 = (centerX - roundW / 2);// 3.设置画大圆环颜色paint.setColor(Color.parseColor("#11339ED4"));// 4.设置画笔的风格paint.setStyle(Paint.Style.STROKE);// 5.设置画圆环的宽度paint.setStrokeWidth(roundW);// 6.消除锯齿paint.setAntiAlias(true);// 7.画圆环canvas.drawCircle(centerX, centerY, radius1, paint);}}效果图:
- 绘制深色进度圆弧
圆弧的绘制重点在开始角度和末端角度的计算和确定,因为我们的圆弧代表进度,所以开始角度和末端角度都与进度有关,会跟着进度的变化而变化,所以首先我们的确定当前进度和最大进度。然后就可以计算始末角度了。
定义进度值:private int progress = 0;// 当前进度值private int maxProgress = 100;// 最大进度值
进度改变接口方法:
/** * 更新进度和界面的方法 * * @param progress */public void setProgress(int progress) {if (progress < 0) {progress = 0;} else {this.progress = progress;}invalidate();}计算始末角度:
开始角度 0
末端角度(float)360 * progress / (float)maxProgress核心逻辑:
//绘制深色进度圆弧// 1.设置圆孤的宽度paint.setStrokeWidth(roundW);// 2.设置圆孤进度的颜色paint.setColor(Color.parseColor("#339ED4"));// 3.定义圆弧的形状和大小区域RectF oval = new RectF(centerX - radius1, centerY - radius1, centerX + radius1, centerY + radius1);// 4.设置空心样式paint.setStyle(Paint.Style.STROKE);// 5.根据进度画圆弧canvas.drawArc(oval, 0, (float)360 * progress / (float)maxProgress, false, paint);完整代码(为了测试进度效果,我们先把progress=20,测试完再设置为progress=0):
package com.kedi.myprogressbar;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;public class MyProgressBar extends View {private Paint paint;// 画笔private int roundW;// 圆环宽private int progress = 20;// 当前进度值private int maxProgress = 100;// 最大进度值/** * 更新进度和界面的方法 * * @param progress */public void setProgress(int progress) {if (progress < 0) {progress = 0;} else {this.progress = progress;}invalidate();}public MyProgressBar(Context context) {this(context, null);}public MyProgressBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}/** * 初始化方法 */private void init() {paint = new Paint();roundW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics());}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制浅色圆环// 1.圆心(x,y)坐标值int centerX = getWidth() / 2;int centerY = centerX;// 2.圆环半径int radius1 = (centerX - roundW / 2);// 3.设置画大圆环颜色paint.setColor(Color.parseColor("#11339ED4"));// 4.设置画笔的风格paint.setStyle(Paint.Style.STROKE);// 5.设置画圆环的宽度paint.setStrokeWidth(roundW);// 6.消除锯齿paint.setAntiAlias(true);// 7.画圆环canvas.drawCircle(centerX, centerY, radius1, paint);// 绘制深色进度圆弧// 1.设置圆孤的宽度paint.setStrokeWidth(roundW);// 2.设置圆孤进度的颜色paint.setColor(Color.parseColor("#339ED4"));// 3.定义圆弧的形状和大小区域界限RectF oval = new RectF(centerX - radius1, centerY - radius1, centerX + radius1, centerY + radius1);// 4.设置空心样式paint.setStyle(Paint.Style.STROKE);// 5.根据进度画圆弧canvas.drawArc(oval, 0, (float) 360 * progress / (float) maxProgress, false, paint);}}效果图:
- 添加SeekBar,并通过进度变化控制进度圆弧
这块主要是通过SeekBar进度的改变来更新进度圆弧的动态改变,逻辑很简单,监听SeekBar进度改变,然后把改变的进度通过setProgress()方法传给自定义控件,触发自定义控件重新调用onDraw()方法,根据新进度值重绘圆弧。
完整代码:
<span style="font-weight: normal;"><span style="font-size:14px;">package com.kedi.myprogressbar;import android.app.Activity;import android.os.Bundle;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;public class MainActivity extends Activity {//自定义进度条控件private MyProgressBar pg;//SeekBar控件private SeekBar sb;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();initEvents();}/** * 初始化View */private void initViews(){pg =(MyProgressBar) findViewById(R.id.pg);sb = (SeekBar) findViewById(R.id.sb);}/** * 初始化事件监听与处理 */private void initEvents() {sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//改变圆弧的进度,并重新绘制圆弧,主要是通过触发自定义控件的onDraw()方法达到目的pg.setProgress(progress);}});}}</span></span>效果图:
- 绘制深蓝色实心圆
实心圆的绘制也是通过drawCircle()方法,只是画笔的样式为FILL实心,所以比较简单。
核心代码:
// 绘制深蓝色实心圆 // 1.实心圆半径 int radius2 = centerX - roundW; // 2.实心圆颜色 paint.setColor(Color.parseColor("#336799")); // 3.设置画笔风格为实心 paint.setStyle(Paint.Style.FILL); // 4.画实心圆 canvas.drawCircle(centerX, centerY, radius2, paint);效果图:
- 绘制百分比文本
绘制文本需要知道文本大小,文本字体,文本颜色,文本x,y坐标位置以及文本内容。
文本大小我们定义个成员变量,然后在init()方法中初始化,当然可以对外提供接口方法,设置文本大小,
文本颜色使用白色,当然也可以像文本大小那样定义成员变量,然后初始化,也可对外提供接口方法,设置文本颜色
文本x,y坐标需要根据圆心坐标与文本自身的宽高进行计算。
文本内容是进度百分比,需要根据进度进行计算。(float) progress / (float) maxProgress) * 100
核心逻辑:
// 绘制百分比文本// 1.设置无边框paint.setStrokeWidth(0);// 2.设置字体颜色paint.setColor(Color.WHITE);paint.setAntiAlias(true);// 3.设置字体大小,定义成员变量textSize,然后在初始化方法中赋初始值paint.setTextSize(textSize);// 4.设置字体paint.setTypeface(Typeface.DEFAULT_BOLD);// 5.计算进度百分比int percent = (int) (((float) progress / (float) maxProgress) * 100);// 6.测量字体宽度float textWidth = paint.measureText(percent + "%");// 7.画出进度百分比文本canvas.drawText(percent + "%", centerX - textWidth / 2, centerY + textSize / 2, paint);
完整代码:
package com.kedi.myprogressbar;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Typeface;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;public class MyProgressBar extends View {private Paint paint;// 画笔private int roundW;// 圆环宽private int textSize;// 字体大小private int progress = 0;// 当前进度值private int maxProgress = 100;// 最大进度值/** * 更新进度和界面的方法 * * @param progress */public void setProgress(int progress) {if (progress < 0) {progress = 0;} else {this.progress = progress;}invalidate();}/** * @param context */public MyProgressBar(Context context) {this(context, null);}/** * @param context * @param attrs */public MyProgressBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}/** * @param context * @param attrs * @param defStyleAttr */public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}/** * 初始化方法 */private void init() {paint = new Paint();roundW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics());textSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 25, getResources().getDisplayMetrics());}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制浅色圆环// 1.圆心(x,y)坐标值int centerX = getWidth() / 2;int centerY = centerX;// 2.圆环半径int radius1 = (centerX - roundW / 2);// 3.设置画大圆环颜色paint.setColor(Color.parseColor("#11339ED4"));// 4.设置画笔的风格paint.setStyle(Paint.Style.STROKE);// 5.设置画圆环的宽度paint.setStrokeWidth(roundW);// 6.消除锯齿paint.setAntiAlias(true);// 7.画圆环canvas.drawCircle(centerX, centerY, radius1, paint);// 绘制深色进度圆弧// 1.设置圆孤的宽度paint.setStrokeWidth(roundW);// 2.设置圆孤进度的颜色paint.setColor(Color.parseColor("#339ED4"));// 3.定义圆弧的形状和大小区域界限RectF oval = new RectF(centerX - radius1, centerY - radius1, centerX + radius1, centerY + radius1);// 4.设置空心样式paint.setStyle(Paint.Style.STROKE);// 5.根据进度画圆弧canvas.drawArc(oval, 0, (float) 360 * progress / (float) maxProgress, false, paint);// 绘制深蓝色实心圆// 1.实心圆半径int radius2 = centerX - roundW;// 2.实心圆颜色paint.setColor(Color.parseColor("#336799"));// 3.设置画笔风格为实心paint.setStyle(Paint.Style.FILL);// 4.画实心圆canvas.drawCircle(centerX, centerY, radius2, paint);// 绘制百分比文本// 1.设置无边框paint.setStrokeWidth(0);// 2.设置字体颜色paint.setColor(Color.WHITE);// 3.设置字体大小paint.setTextSize(textSize);// 4.设置字体paint.setTypeface(Typeface.DEFAULT_BOLD);// 5.计算进度百分比int percent = (int) (((float) progress / (float) maxProgress) * 100);// 6.测量字体宽度float textWidth = paint.measureText(percent + "%");// 7.画出进度百分比文本canvas.drawText(percent + "%", centerX - textWidth / 2, centerY + textSize / 2, paint);}}效果图:
到此实现的效果已经与我们一开始看到的效果分毫不差了。
- 自定义属性,使进度条样式可配置(扩展部分)
效果已经实现完了,但是如果我的项目中需要一个其它主题风格的进度条,那我们不得不重新Copy一份,然后修改其中的颜色值什么的,这样的自定义控件显然不够灵活和通用,如果进度条提供了对主题风格的定制接口那就灵活不少,所以接下来做为扩展部分,要做的是为进度条提供主题风格定制途径---自定义属性与Setter方法。
经分析,把与样式相关的特征都定义成成员变量,有如下几个:
//圆环相关成员变量 private int roundW;// 圆环宽 private int roundColor;//圆环颜色//圆弧相关成员变量 private int progress;// 当前进度值 private int progressColor;//进度圆弧颜色 private int maxProgress = 100;// 最大进度值//实心圆相关成员变量 private int circleColor;//实心圆颜色 //百分比文本相关成员变量 private int textColor;//字体颜色 private int textSize;// 字体大小
定义自定义属性文件values/attrs.xml,并定义成上面成员变量一一对应的自定义属性:
<?xml version="1.0" encoding="utf-8"?><resources xmlns:android="http://schemas.android.com/apk/res/android"> <declare-styleable name="MyProgressBarSytle"> <!-- 圆环相关 --> <attr name="roundW" format="dimension" /> <attr name="roundColor" format="color" /> <!-- 圆弧相关 --> <attr name="progress" format="integer" /> <attr name="progressColor" format="color" /> <attr name="maxProgress" format="integer" /> <!-- 实心圆相关 --> <attr name="circleColor" format="color" /> <!-- 百分比文本相关 --> <attr name="textColor" format="color" /> <attr name="textSize" format="dimension" /> </declare-styleable></resources>构造方法中获取自定义属性,然后初始化上面的那几个成员变量(将原来的值做为默认值):
public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(attrs);}private void init(AttributeSet attrs) {paint = new Paint(); TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyProgressBarSytle); roundW = (int) typedArray.getDimension(R.styleable.MyProgressBarSytle_roundW, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics())); roundColor = typedArray.getColor(R.styleable.MyProgressBarSytle_roundColor, Color.parseColor("#11339ED4")); progress = typedArray.getInt(R.styleable.MyProgressBarSytle_progress, 0); progressColor = typedArray.getColor(R.styleable.MyProgressBarSytle_progressColor, Color.parseColor("#339ED4")); circleColor = typedArray.getColor(R.styleable.MyProgressBarSytle_circleColor, Color.parseColor("#336799")); textColor = typedArray.getColor(R.styleable.MyProgressBarSytle_textColor, Color.parseColor("#ffffff")); textSize = (int) typedArray.getDimension(R.styleable.MyProgressBarSytle_textSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 25, getResources().getDisplayMetrics())); typedArray.recycle();}
将绘制逻辑各分部中样式原来的值,换成成员变量:
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制浅色圆环// 1.圆心(x,y)坐标值int centerX = getWidth() / 2;int centerY = centerX;// 2.圆环半径int radius1 = (centerX - roundW / 2);// 3.设置画大圆环颜色paint.setColor(roundColor);// 4.设置画笔的风格paint.setStyle(Paint.Style.STROKE);// 5.设置画圆环的宽度paint.setStrokeWidth(roundW);// 6.消除锯齿paint.setAntiAlias(true);// 7.画圆环canvas.drawCircle(centerX, centerY, radius1, paint);// 绘制深色进度圆弧// 1.设置圆孤的宽度paint.setStrokeWidth(roundW);// 2.设置圆孤进度的颜色paint.setColor(progressColor);// 3.定义圆弧的形状和大小区域界限RectF oval = new RectF(centerX - radius1, centerY - radius1, centerX + radius1, centerY + radius1);// 4.设置空心样式paint.setStyle(Paint.Style.STROKE);// 5.根据进度画圆弧canvas.drawArc(oval, 0, (float) 360 * progress / (float) maxProgress, false, paint);// 绘制深蓝色实心圆// 1.实心圆半径int radius2 = centerX - roundW;// 2.实心圆颜色paint.setColor(circleColor);// 3.设置画笔风格为实心paint.setStyle(Paint.Style.FILL);// 4.画实心圆canvas.drawCircle(centerX, centerY, radius2, paint);// 绘制百分比文本// 1.设置无边框paint.setStrokeWidth(0);// 2.设置字体颜色paint.setColor(textColor);paint.setAntiAlias(true);// 3.设置字体大小paint.setTextSize(textSize);// 4.设置字体paint.setTypeface(Typeface.DEFAULT_BOLD);// 5.计算进度百分比int percent = (int) (((float) progress / (float) maxProgress) * 100);// 6.测量字体宽度float textWidth = paint.measureText(percent + "%");// 7.画出进度百分比文本canvas.drawText(percent + "%", centerX - textWidth / 2, centerY + textSize / 2, paint);}如果我们希望通过代码也可以修改这些样式值,就对外提供Setter方法:
/** * 设置圆环宽度 * @param roundW */public void setRoundW(int roundW) {this.roundW = roundW;}/** * 设置圆环颜色 * @param roundColor */public void setRoundColor(int roundColor) {this.roundColor = roundColor;}/** * 设置进度圆弧颜色 * @param progressColor */public void setProgressColor(int progressColor) {this.progressColor = progressColor;}/** * 设置最大进度值 * @param maxProgress */public void setMaxProgress(int maxProgress) {this.maxProgress = maxProgress;}/** * 设置实心圆颜色 * @param circleColor */public void setCircleColor(int circleColor) {this.circleColor = circleColor;}/** * 设置百分比进度文本颜色 * @param textColor */public void setTextColor(int textColor) {this.textColor = textColor;}/** * 设置百分比进度文本字体大小 * @param textSize */public void setTextSize(int textSize) {this.textSize = textSize;}/** * 更新进度和界面的方法 * * @param progress */public void setProgress(int progress) {if (progress < 0) {progress = 0;} else {this.progress = progress;}invalidate();}最后演示一下使用自定义属性定制主题的方式:
(1)在根布局中添加命名空间
xmlns:my="http://schemas.android.com/apk/res-auto"
(2)使用自定义属性并指定属性值
完整布局代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:my="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <com.kedi.myprogressbar.MyProgressBar android:id="@+id/pg" android:layout_width="120dp" android:layout_height="120dp" android:layout_centerInParent="true" android:padding="5dp" my:circleColor="#ACD900" my:maxProgress="100" my:progressColor="#FF6400" my:roundColor="#316900" my:roundW="8dp" my:textColor="#EE3400" my:textSize="20sp" > </com.kedi.myprogressbar.MyProgressBar> <SeekBar android:id="@+id/sb" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/pg" android:layout_margin="20dp" android:max="100" /></RelativeLayout>效果图:
到此就完成了比较灵活的圆形进度条的制作。
更多相关文章
- 实用的Log打印类封装,助尼快速定位源码(android)
- Android中直播视频技术探究之---采集摄像头Camera视频源数据进行
- eBook 功能模块二之设置模块
- android NDK开发在本地C/C++源代码中设置断点单步调试详细教程
- Android好看的日期时间选择器,自定义的时钟组件
- Android:在service和activity之中,实现音乐播放进度条传递信息的两
- Android(安卓)Studio代码自己主动提示无效(not available in Powe
- android GridView设置边框教程。
- 仿写Android屏幕解锁小应用