本文主要是介绍Android基础巩固提升,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Android基础提升学习之旅:1、Android自定义控件
<.View的工作原理
.measure操作用于计算视图的大小(视图的宽和高),在View中定义为final类型,要求子类不能修改
measure()会调用onMeasure(),子类重写onMeasure()方法修改计算视图大小的方式,并通过setMeasuredDimension()保存计算结果
关于MeasureSpec:
UPSPECIFIED:父容器对子容器没有任何限制,子容器想要多大就多大
EXACTLY:父容器为子容器设置了尺寸
AT_MOST:子容器可以是声明大小内的任意大小(当ListView嵌套了ScrollView时,ListView只能显示一行,此时重写onMeasure函数,并设置高度为AT_MOST即可)
.layout操作用于设置视图在屏幕中显示的位置,layout()会调用setFrame(l,t,r,b)子视图在父视图中的具体位置
.draw操作利用前两个操作得到的参数将视图显示在屏幕上,到这里整个视图的绘制工作完成了
在view中onDraw()是个空函数,具体的视图都要重写这个函数来实现自己的显示
ViewGrope则不需要实现onDraw函数,因为容器是没有内容的.
dispatchDraw()函数专门为容器类准备的,因此ViewGroup类必须实现该方法.
<.编写继承自View的子类
.继承已有的控件
.继承一个布局文件
.继承View类
<.为自定义类增加属性
.通过构造函数View(Context con,AttributeSet a)引入的AttributeSet查找XML布局的属性名称
MyView(Context con,AttributeSet a){
super(con,a);
int textid = a.getAttributeResourceValue(null,"Text",0);
int srcid = a.getAttributeResourceValue(null,"Src",0);
String textStr = getResource().getText(textid).toString();
}
布局文件引用:
<com.demo.app.view.MyView
android:layout_width="match_parent"
android:layout_height="wrap_content"
Text="@string/you_know"
Src="@drawable/time"/>
.通过XML为ViewGroup注册属性
MyView(Context con,AttributeSet a){
super(con,a);
TypedArray ta = con.obtainStyledAttributes(a,R.styleable.MyView);
int textid = ta.getResourceId(R.styleable.MyView_Text,0);
int srcid = ta.getResourceId(R.styleable.MyView_Src,0);
int orienid = ta.getInt(R.styleable.MyView_Oriental,0);
TextView tv = new TextView(con);
ImageView iv = new ImageView(con);
tv.setText(getResource.getText(textid).toString());
iv.setImageResource(srcid);
setOrientation(orienid == 1?LinearLayout.HORIZONTAL:LinearLayout.VERTICAL);
addView(iv);
addView(tv);
ta.recycle();
}
res/values/attrs.xml文件中加入:
<declare-styleable name="MyView">
<attr name="Text" format="reference"></attr>
<attr name="Oriental">
<enum name="Horizontal" value="1"></enum>
<enum name="vertical" value="0"></enum>
</attr>
<attr name="Src" format="reference|integer"></attr>
</declare-styleable>
布局文件引用:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:uview="http://schemas.android.com/apk/res/com.demo.app"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.demo.app.view.MyView
android:layout_width="match_parent"
android:layout_height="match_parent"
uview:Text="@string/you_know"
uview:Src="@drawable/time"
uview:Oriental="Vertical"/>
</LinearLayout>
备注:这里自定义控件新增属性的值都是通过布局文件引用直接赋值,也可以定义个接口由代码动态赋值。
<.绘制控件
在onDraw()函数里面绘制
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.RED);
InputStream inputStream = getResources().openRawResource(mSrcId);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
canvas.drawBitmap(bitmap,0,0,paint);
canvas.drawText(mTextStr,30,30,paint);
}
<.响应用户消息
.一般View重写onTouchEvent方法,ViewGroup重写onTouchEvent和dispatchTouchEvent方法
.事件分发只限于ACTION_DOWN事件,由ACTION_DOWN确定需要处理完整Touch请求的View,ACTION_MOVE和ACTION_UP直接由该View处理
<.自定义回调函数
.定义一个接口
public interface ICallBack{
public void onClick(String s);
}
.初始化接口变量
ICallBack icallBack = null;
.对外提供的使用接口的函数
public void setOnClick(ICallBack iBack){
icallBack = iBack;
}
.使用接口
icallBack.onClick("haha");
备注:外部通过setOnClick(ICallBack)方法实现ICallBack接口的onClick(String)方法,自定义控件使用外部实现的方法。
2、Android事件分发机制
ViewGroup接收事件--》ViewGroup调用dispatchTouchEvent方法,如果在ACTION_DOWN时dispatchTouchEvent返回false,则后续ACTION_MOVE和ACTION_UP都接收不到了
如果ACTION_DOWN时dispatchTouchEvent返回true则后续动作都可以继续分发
在事件传递给子View或者ViewGroup之前,要先经过ViewGroup的拦截器onInterceptTouchEvent判断,
如果onInterceptTouchEvent返回true就会拦截,最终传递给本ViewGroup的onTouchEvent方法
如果onInterceptTouchEvent返回false就不拦截,传递给子View或者ViewGroup的dispatchTouchEvent
事件传递过程--》遍历所有直属子View和ViewGroup,将事件传递给发生点击事件的直属子View/ViewGroup,
直属子View/ViewGroup再调用自己的dispatchTouchEvent进行分发,
直到某级的ViewGroup的onInterceptTouchEvent返回true,将事件传递给自己的onTouchEvent方法进行处理
或者没有任何ViewGroup的拦截器拦截事件,事件最终传递给最底层的View的onTouchEvent方法
如果onTouchEvent返回true,就会消费掉本次事件,
如果onTouchEvent返回false,则事件依次向上传递给自己上一级的view/ViewGroup的onTouchEvent,直到某个onTouchEvent返回true,
如果没有任何一个onTouchEvent返回true,则事件在最上层onTouchEvent返回false之后消失掉。
dispatchTouchEvent方法用来分发上层传递过来的事件,在View和ViewGroup中都有实现。
.View的dispatchTouchEvent方法实现:
public boolean dispatchTouchEvent(MotionEvent ev){
....//其他处理,在此不管
return onTouchEvent(event);
}-->决定是否自己消费掉本次事件,不执行分发工作,一般View不重写dispatchTouchEvent方法
View对象的TouchListener的onTouch方法会先于View自己的onTouchEvent方法执行,是由dispatchTouchEvent决定的
这篇关于Android基础巩固提升的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!