在Android的开发过程中,一路走来发现,自定义组件是比较困难的。想把自定义控件写好,不下一 番功夫不投入一些精力是写不好控件的。
接下来老于就带你走进自定义控件的入门殿堂
相信大家都知道:写一个自定义组件首先要继承于所要自定义组件的类。比如
public class MyTextView extends TextView{
构造方法{}
onMeasure{}方法
}
其中,我们要做到的首先要重写其构造方法;
其中2个有参数的构造方法必写,其余的有残的构造方法可以不写,因为其归根到底,其调用的还是2个参数的构造方法;
现在写的 UI ,很多自定义组件,父 view 和子 view 都需要接收事件,然后处理。如果不弄明白它的事件传递机制,很难拥有好的用户体验。
Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去,这个是最基本的。
在 View 中跟 Touch 相关的事件有 dispatchTouchEvent , interceptTouchEvnet , onTouchEvent 三种。 dispatchTouchEvent 是负责分发事件的,事件从 activity 传递出来之后,最先到达的就是最顶层 view 的 dispatchTouchEvent ,然后它进行分发,如果返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。
如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。(我说的一次事件指的是 down 到 up 之间的一系列事件)
接下来我就给大家来个最简单的自定义Linearlayout来实现自定义的TitleBar;
java代码:
public class TitleBarNew extends LinearLayout {
/** 给自定义Titlear所设定的标题 */
private TextView title;
/**
给自定义Titlear
所设定的
标题图片 */
private ImageView title_iv;
/**
给自定义Titlear所设定的
设置 图片*/
private ImageView setting_icon;
/**
给自定义Titlear所设定的
回退键 */
private ImageView return_icon;
private LinearLayout titlebar_bg;
private ImageView titlebar_downline;
public TitleBarNew(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typeArray = context.obtainStyledAttributes(attrs,
R.styleable.titlebar, 0, 0);
LayoutInflater.from(context).inflate(R.layout.te_layout_titlebar, this);
titlebar_bg = (LinearLayout) findViewById(R.id.titlebar_bg);
title = (TextView) findViewById(R.id.titlebar_title_tv);
title_iv=(ImageView) findViewById(R.id.titlebar_title_iv);
titlebar_downline=(ImageView) findViewById(R.id.titlebar_downline);
setting_icon = (ImageView) findViewById(R.id.titlebar_setting_icon);
return_icon = (ImageView) findViewById(R.id.titlebar_return_icon);
if (null != typeArray.getString(R.styleable.titlebar_titles)) {
title.setText(typeArray.getString(R.styleable.titlebar_titles));
title.setVisibility(View.VISIBLE);
title_iv.setVisibility(View.GONE);
}else{
title.setVisibility(View.GONE);
title_iv.setVisibility(View.VISIBLE);
}
if(null!=typeArray.getDrawable(R.styleable.titlebar_title_iv)){
title_iv.setImageDrawable(typeArray.getDrawable(R.styleable.titlebar_title_iv));
}
if(null!=typeArray.getDrawable(R.styleable.titlebar_return_icon)){
return_icon.setVisibility(View.VISIBLE);
return_icon.setImageDrawable(typeArray.getDrawable(R.styleable.titlebar_return_icon));
}
if(null!=typeArray.getDrawable(R.styleable.titlebar_setting_icon)){
setting_icon.setVisibility(View.VISIBLE);
setting_icon.setImageDrawable(typeArray.getDrawable(R.styleable.titlebar_setting_icon));
}
}
/** 回退图标显示及绑定监听事件 */
public void setLeftButtonShowAndClick(int visibility,
OnClickListener backOnClickListener) {
return_icon.setVisibility(visibility);
return_icon.setOnClickListener(backOnClickListener);
}
/** 设置图标显示及绑定监听事件 */
public void setRightButtonShowAndClick(int visibility,
OnClickListener settingOnClickListener) {
setting_icon.setVisibility(visibility);
if(settingOnClickListener!=null){
setting_icon.setOnClickListener(settingOnClickListener);
}
}
/** 设置图标更换*/
public void setRightButtonIcon(int resId) {
setting_icon.setImageResource(resId);
}
/** 设置titlebar的背景色 */
public void setTitlebarColor(String colorString,int resId) {
titlebar_bg.setBackgroundColor(Color.parseColor(colorString));
titlebar_downline.setImageResource(resId);
}
}
引入的布局代码:
layout : te_layout_titlebar
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="
http://schemas.android.com/apk/res/android"
android:id="@id/titlebar_bg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/titlebar_bg" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:id="@id/titlebar_return_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/te_title_return"
android:visibility="invisible"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<TextView
android:id="@id/titlebar_title_tv"
style="@style/TextView.Shadowed.Inverse"
android:textAppearance="?android:textAppearanceLargeInverse"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:visibility="visible"
android:textColor="@android:color/white"
android:textSize="22sp"/>
<ImageView
android:id="@id/titlebar_title_iv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/te_home_titlebar_title"
android:visibility="gone" />
<ImageView
android:id="@id/titlebar_setting_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:src="@drawable/te_setting_icon"
android:visibility="invisible"/>
</LinearLayout>
<ImageView
android:id="@id/titlebar_downline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/te_titlebar_downline"/>
</LinearLayout>
在自定义TitleBar类里面的构造方法:其实用到: TypedArray typedarray = context.obtainStyledAttributes(attributeset,
AppAttributes.d, 0, 0);是再好不过了,接下来我会给大家详细讲解
TypedArray
的使用情况。