您的位置:首页 > 其它

自定义视图的简单应用

2017-08-16 17:29 309 查看
1、在res/values目录下新建attrs.xml文件:

<resources>
<declare-styleable name="myStyleable">
<attr name="max" format="integer"/>
<attr name="progress" format="integer"/>
<attr name="textSize" format="dimension"/>
<attr name="smallBgColor" format="color"/>
<attr name="progressColor" format="color"/>
</declare-styleable>

</resources>


format(自定义属性的格式)可选内容有integer、dimension(尺寸)、color、boolean、enum(枚举值)、flag(位或运算)、float、fraction(百分数)、reference(参考某一ID、默认)、string.

<declare-styleable name =
"名称">

      <attr name = "background" format =
"reference" />

</declare-styleable>

eg:

<ImageView

     android:layout_width = "42dip"

     android:layout_height = "42dip"

     android:background = "@drawable/图片ID"

                     />

2、自定义视图:

public class XykjProgressBar extends View {
//进度条的半径
private int radius;
//圆心
private int cx, cy;
//画笔
private Paint paint;
//进度的最大值
private int max = 100;

//进度值
private int progress;
//文本大小
private int textSize;
//内部小圆的背景色
private int smallBgColor = 0xff3F51B5;
//进度条的颜色
private int progressColor = 0xffFF4081;

public XykjProgressBar(Context context) {
super(context);
init();
}

public XykjProgressBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
//解析自定义属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.myStyleable);
textSize = ta.getDimensionPixelSize(R.styleable.myStyleable_textSize, 0);  //sp dp dip
max = ta.getInteger(R.styleable.myStyleable_max,100);
progress = ta.getInteger(R.styleable.myStyleable_progress,0);
smallBgColor = ta.getColor(R.styleable.myStyleable_smallBgColor,0xff3F51B5);
progressColor = ta.getColor(R.styleable.myStyleable_progressColor,0xffFF4081);
//释放资源
ta.recycle();
init();
}

private void init() {
paint = new Paint();
paint.setAntiAlias(true);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setColor(smallBgColor);
//画中间的小圆
canvas.drawCircle(cx, cy, radius - 10, paint);
//文本
int num = 100 * progress / max;  //50 100 -->50%
String str = num + "%";
//获取文本的边框
Rect bound = new Rect();
paint.setTextSize(textSize);
paint.getTextBounds(str, 0, str.length(), bound);
int x = cx - bound.centerX();
int y = cy - bound.centerY();
paint.setColor(Color.WHITE);
//画进度文本
canvas.drawText(str, x, y, paint);
//进度的弧线
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
paint.setColor(progressColor);
//计算所跨越的弧度
int degree = 360 * progress / max;
RectF rect = new RectF(cx - radius, cy - radius, cx + radius, cy + radius);
//画弧线
canvas.drawArc(rect, -90, degree, false, paint);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getSize(widthMeasureSpec);
int height = getSize(heightMeasureSpec);
//初始化圆心
cx = width / 2;
cy = height / 2;
//取最短的边的一半作为进度半径
radius = width < height ? cx : cy;
radius -= 10;
//如果没有默认值则,初始化文本大小
if (textSize == 0) {
textSize = radius / 2;
}
setMeasuredDimension(width, height);
}

//获取尺寸方法(自定义的根据模式获取,wrap_content时设置默认值为80)
private int getSize(int measureSpec) {
//获取测量模式
int mode = MeasureSpec.getMode(measureSpec);
int size = 80;
if (mode == MeasureSpec.EXACTLY) {
//精确的,固定的值,match_parent或者100  200
size = MeasureSpec.getSize(measureSpec);
}/*else if(mode == MeasureSpec.AT_MOST){
//不确定,如wrap_content
size = 80;
}*/
return size;
}

public int getMax() {
return max;
}

public void setMax(int max) {
this.max = max;
}

public int getProgress() {
return progress;
}

public void setProgress(int progress) {
if (this.progress != progress && progress <= max) {
this.progress = progress;
invalidate();
}
}

public int getTextSize() {
return textSize;
}

public void setTextSize(int textSize) {
this.textSize = textSize;
}

public int getSmallBgColor() {
return smallBgColor;
}

public void setSmallBgColor(int smallBgColor) {
this.smallBgColor = smallBgColor;
}

public int getProgressColor() {
return progressColor;
}

public void setProgressColor(int progressColor) {
this.progressColor = progressColor;
}
}


3、在主界面中引用:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layo
bc97
ut_height="match_parent"
tools:context="com.xykj.myprogressbar.MainActivity">

<com.xykj.myprogressbar.XykjProgressBar
android:id="@+id/progress_bar"
android:layout_width="200dp"
android:layout_height="200dp"
app:textSize="30sp"
app:smallBgColor="#ff000000"/>

<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click" />

</LinearLayout>


java代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

XykjProgressBar pBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pBar = (XykjProgressBar) findViewById(R.id.progress_bar);
pBar.setMax(100);
pBar.setProgress(10);
pBar.setTextSize(50);
findViewById(R.id.btn).setOnClickListener(this);
}

@Override
public void onClick(View v) {
int p = pBar.getProgress();
p+=5;
pBar.setProgress(p);
}
}


结果如下图:



面试题:介绍下实现一个自定义View的基本流程:

1、自定义view属性,编写attrs.xml文件

2、在layout布局中引用,同时引用命名空间

3、在view的构造方法中获得我们自定义的属性,在自定义的控件中进行读取

4、重写onMeasure()方法

5、重写onDraw()方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: