一、自定义View第一课:简单实现自定义按钮回顾
(1)在第一节《自定义View精炼详解第(一)课:基础理论部分和简单小实现》的讲述中,我们掌握了自定义View的概念和三种的实现自定义View的方式:①继承现有控件实现;②继承多个现有控件实现,即继承现有布局实现;③继承根View实现。其中前面①②是开发中最为常见,也是最为有效的自定义View方式,③是完全的自定义一个不存在的控件,其排版、优化、效率都是有严格要求的。
(2)自定义View的难点:①自定义控件的属性;②自定义控件的关键回调函数;③自定义View的事件分发机制和滑动失效处理。以上就是自定义View的三大难点,在第一节的讲述中,我们自定义了一个简单的按钮,效果是:在点击时可以实现不同的颜色切换。在这个实例中,并不涉及上述的三个难点,今天自定义View的讲解开始往深度延伸,开始讲解第一个难点——自定义控件的属性。
二、上代码,简单实现——标题栏
(1)标题栏定义,从初代iphone机就开始配备了,因为iphone只有一个按键,所以需要屏幕上有其他可以让用户操作和实现交互的按钮。iphone标题栏是放置在屏幕顶部的,添加两个按钮和一段文字,经典界面。
后来,Android沿用了iphone的风格,也在顶部设置了标题栏,创建主Activity时,比如选择EmptyActivity,创建之后的页面会自动含有一个标题栏,如下所示;
我们现在要做的是就是,不用系统自带的标题栏,然后自己自定义一个标题栏,实现和iphone一样的效果。因为标题栏会在一个应用程序的很多界面复用,所以如果把标题栏自定义好,然后在每个Activity的界面布局中引入时即可直接引入这个标题栏,实现了代码的复用,而且非常好维护(产品汪说这个标题小了,要加大,我们可以很容易就实现所有界面的同步更换)。View控件代码的复用的也是自定义View的一个优势。
(2)上代码,具体实现
①创建title.xml布局;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_bg">
<Button
android:id="@+id/title_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:background="@drawable/back_bg"
android:text="Back"
android:textColor="#fff" />
<TextView
android:id="@+id/title_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:text="Title Text"
android:textColor="#fff"
android:textSize="24sp" />
<Button
android:id="@+id/title_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:background="@drawable/edit_bg"
android:text="Edit"
android:textColor="#fff" />
</LinearLayout>
②创建自定义标题栏TitleLayout类,引用title.xml布局,并实现简单的点击事件;
public class TitleLayout extends LinearLayout {
public TitleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title, this);
Button titleBack = (Button) findViewById(R.id.title_back);
Button titleEdit = (Button) findViewById(R.id.title_edit);
titleBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((Activity) getContext()).finish();
}
});
titleEdit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getContext(), "You clicked Edit button",
Toast.LENGTH_SHORT).show();
}
});
}
}
③主布局main_activity.xml文件中引入自定义标题栏TitleLayout;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.uicustomviews.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
④主Activity中引入main_activity.xml布局文件;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionbar = getSupportActionBar();
if (actionbar != null) {
actionbar.hide();
}//该代码段的作用是用来隐藏系统自带的标题栏的,见上文
}
}
———————————————————我是重点分隔线————————————————————
(3)为标题栏中文字加上属性
现在我们假定标题栏中两个按钮显示的东西不变,中间显示的文字是可以变化的,我们要实现这种效果,就要用到自定义View中一个很重要的知识点:自定义属性
自定义属性如何使用,一共分三步:
1)attrs.xml添加属性(values文件夹下面的文件);
2)与自定义控件(类)绑定属性;
3)在全局布局文件中使用这个属性。
我们在(3)中的代码基础上进行修改
①新建一个attrs.xml文件,name="CustomView",在其中添加标题需要的属性——文字大小,文字颜色,文字内容;
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomView">
<attr name="color" format="color"/>
<attr name="font" format="dimension"/>
<attr name="text" format="string"/>
</declare-styleable>
</resources>
②title.xml布局中去掉TextView原来的text属性;
③在TitleLayout类,写出布局的回调函数和绑定添加的属性CustomView;
public class CustomView extends View {
//文字内容
private String customText;
//文字的颜色
private int customColor;
//文字的字体大小
private int fontSize;
public void setView(String customText,int customColor,int fontSize) {
if(customText!= null){
customText.setText(customText);
}
if(customColor!= null){
customColor.setColor(customColor);
}
if(fontSize!= null){
fontSize.setText(fontSize);
}
}
/**
获取自定义属性
*/
private void initCustomAttrs(Context context, AttributeSet attrs) {
//获取自定义属性。
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
//获取字体大小,默认大小是16dp
fontSize = (int) ta.getDimension(R.styleable.CustomView_font, 16);
//获取文字内容
customText = ta.getString(R.styleable.CustomView_text);
//获取文字颜色,默认颜色是BLUE
customColor = ta.getColor(R.styleable.CustomView_color, Color.BLUE);
setView(customText,customColor,fontSize);
ta.recycle();
}
}
④主布局main_activity.xml应用绑定好的属性;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.uicustomviews.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
CustomView:color="@color/colorAccent"
CustomView:font="16sp"
CustomView:text="hello world"/>
</LinearLayout>
⑤主Activity中引入main_activity.xml布局文件;
小结:通过对标题栏中的文字,加上属性(文字大小,文字颜色,文字内容),就可以构建一个模块代码段,这段代码不断可以在这个应用程序中使用,还可以在其他应用程序中使用,只要根据不同应用程序的风格做好相应的标题栏的属性设定,就可以实现我们想要的不同标题栏的效果。
本节中对于自定义View的属性讲解就到这里结束了,读者只需把与自定义View属性的“三板斧”记住,平时开发中就可以很快实现想要的结果。