大二从上学期开学开始,学习Android不到两个月,和几个做过安卓端app的同学一块做了一个小项目,应用段主要我负责来做。在实现一些个性化的功能时难免会用到一些个性化的控件来凸显这些功能。由于对这方面没有怎么学习,只是在学习使用一些自带的控件。所以需要一些好看的控件多是从github上compile来的,这样在以后的维护会有些麻烦,而且大多数的应用都是用着自己设计的控件。
所以,本着兴趣和以后的开发,控件这块决定搞一搞,以后也做个UI达人,~233333.
好了,进入正题,
这是开篇介绍,当然是从最简单的开始。
那么怎样来创建一个新的控件呢?
这得看需求是怎样的了。
1.需要在原生控件的基本功能上进行扩展,这个时候你只需要继承并对控件进行扩展。通过重写它的事件,onDraw ,但是始终都保持都父类方法的调用。如从已有的高级控件上继承,例如继承一个TextView。
2.需要几个控件的功能的加和,这个时候要把控件组合起来,就是通过合并几个控件来生成一个新控件。比如在ListView中用适配器来将多种控件有机的结合在一起,又如写一个控件是多个控件的组合,一般是自定义布局,可以用一个类继承一个布局。这个布局中包含多个控件。
3.白手起家自己创建一个新的控件。即直接从View,ViewGroup开始绘制控件。
那么根据从上文中学习的知识,我们来创建第一个控件 : MoveBall(改了个名字,山寨货)
首先呢,我们创建这个类来继承View,详细点注释应该很明白,不在一一赘述:
/** * Created by scrovor on 2016/5/1. */ public class MoveBall extends View { private float circleX = 40; private float circleY = 50; private float circleR = 15; private TypedArray typedArray; public MoveBall(Context context,AttributeSet attrs) { //直传context 加载控件会出问题 见 上面链接里的解释 super(context, attrs); typedArray = context.obtainStyledAttributes(attrs, R.styleable.MoveBall); //从attrs.xml获取控件属性的值 } @Override public void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); //定义画笔 paint.setColor(typedArray.getColor(R.styleable.MoveBall_ballcolor,Color.GREEN)); //优先使用控件设置的属性,未设置则用默认属性 绿色 canvas.drawCircle(circleX,circleY,typedArray.getDimension(R.styleable.MoveBall_radius,circleR),paint); //同上 } public float getCircleX(){ return circleX; } public void setCircleX(float circleX){ this.circleX = circleX; } public float getCircleY(){ return circleY; } public void setCircleY(float circleY){ this.circleY = circleY; } public float getCircleR(){ return circleR; } public void setCircleR(float circleR){ this.circleR = circleR; } }重要的方法自然是重写的onDraw(Canvas canvas)这个方法,
Canvas中文的意思是画布,有了Paint 这个画笔(我们已经为这个画笔设置好了属性:颜色),我们就可以在这里乱涂乱画了。
好了以上这些都不是我主要想解释的,我主要解释怎为自己的控件加属性:
那就是代码中的关键的 TypedArray 对象 他用来从 attrs.xml中读取一个属性组,这个属性组对应的值自然是在控件布局中设置的,TypedArray简单的用法:
TypedArray typedarray = context.obtainStyledAttributes(attrs,R.styleable.MoveBall);
attrs.xml是自己创建的在values下的,
里面内容:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MoveBall"> <attr name="ballcolor" format="color"/> <attr name="radius" format="dimension" /> </declare-styleable> </resources>format 用来指参数的格式:integer float dimension color ...
name 自然就是我们说的属性名字了
获取属性的值的方法:
typedArray.getDimension(R.styleable.MoveBall_radius,circleR);需要注意的是getDimension这个方法返回的是float类型,当然都需要指明默认的值circleR。
一切就绪,我们来添加这个控件:
<com.example.lenovo.widgetlearn.Widget.MoveBall android:id="@+id/moveball" android:layout_width="match_parent" android:layout_height="match_parent" my:ballcolor="@color/colorAccent" my:radius="50dp"/>my需要在根布局(暂且这么叫吧, )那里声明一下:
xmlns:my="http://schemas.android.com/apk/res-auto"然后在主activity那里对这个控件进行调用:
private MoveBall moveBall; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); moveBall = (MoveBall)findViewById(R.id.moveball); moveBall.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { moveBall.setCircleX(motionEvent.getX()); //根据点击的x ,y 设置球的位置 moveBall.setCircleY(motionEvent.getY()); moveBall.invalidate(); //重绘布局 return false; } }); }
最后效果图:
OK,总结下这个小玩具控件:
1,根据要实现的效果,选择继承View.
2,还是效果,写好onDraw,及一些接口函数。
3,创建attrs.xml,为控件设置自定义属性,并在控件类通过TypedArray来调用。
4,在布局中应用控件,使用自己的属性需要加声明。
5,最后在主界面声明控件,根据控件使用的接口来调用控件。
有需要交流学习,错误之处,大家多多指出,虚心学习。