预览一下效果:
素材:
新建一个布局title_bar.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/colorTitle"android:orientation="horizontal"><Buttonandroid:id="@+id/title_back"android:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="center"android:layout_margin="5dp"android:background="@drawable/firefox"android:textSize="24dp" /><TextViewandroid:id="@+id/title_text"android:layout_width="wrap_content"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="24dp" /><Buttonandroid:id="@+id/title_edit"android:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="center"android:layout_margin="5dp"android:background="@drawable/chrome" /></LinearLayout>
现在标题栏布局已经编写完成了,剩下的就是如何在程序中使用这个标题栏了,修改activity_main.xml中的代码,如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><include layout="@layout/title_bar" /></LinearLayout>
只需要通过一行include语句将标题布局引入进来就可以了:
<include layout="@layout/title_bar" />
最后别忘了在MainActivity中将系统自带的标题栏隐藏掉,代码如下所示:
public class MainActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);}}
使用这种方式,不管有多少布局需要添加标题栏,只需要一行include语句就可以了。
----------------------------------------为自定义UI控件添加动作-----------------------------------------------
引入布局的技巧确实解决了重复编写布局代码的问题,但是如果布局中有一些控件要求能够响应事件,还是需要在每个活动中为这些控件单独编写一次事件注册的代码。
通过自定义控件可以解决重复代码的问题。
新建TitleLayout继承自LinearLayout,让它成为我们自定义的标题栏,代码如下:
public class TitleLayout extends LinearLayout {public TitleLayout(Context context, AttributeSet attrs) {super(context, attrs);LayoutInflater.from(context).inflate(R.layout.title_bar, this);}}
首先我们重写了LinearLayout中的带有两个参数的构造函数,在布局中引入TitleLayout控件就会调用这个构造函数。
然后在构造函数中需要对标题栏布局进行动态加载,这就需要借助LayoutInflater实现。
通过LayoutInflater的from()方法可以构建出一个LayoutInflater对象,然后调用inflate()方法就可以动态加载一个布局文件。
inflate()方法接受两个参数,第一个参数是要加载的布局文件的id,第二个参数是给加载好的布局再添加一个父布局。
自定义控件创建之后,需要在布局文件中添加这个自定义控件,修改activity_main.xml中的代码,如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><com.example.uicustomviews.TitleLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"></com.example.uicustomviews.TitleLayout></LinearLayout>
最后尝试为标题栏中的按钮注册点击事件,修改TitleLayout中的代码,如下所示:
public class TitleLayout extends LinearLayout {public TitleLayout(Context context, AttributeSet attrs) {super(context, attrs);//动态加载布局文件LayoutInflater.from(context).inflate(R.layout.title_bar, this);Button titleBack = (Button) findViewById(R.id.title_back);Button titleEdit = (Button) findViewById(R.id.title_edit);titleBack.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//结束当前Activity((Activity) getContext()).finish();}});titleEdit.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(getContext(), "You clicked Edit button", Toast.LENGTH_SHORT).show();}});}}
这样的话,当我们在一个布局中引入TitleLayout,返回按钮和编辑按钮的点击事件已经自动实现好了,节省了很多编写重复代码的工作。
总结:自定义UI控件的创建步骤
第一步:使用XML绘制自定义的UI控件
第二步:创建自定义控件,重写LinearLayout:
1.引入UI控件:LayoutInflater.from(context).inflate(R.layout.title,this);
2.引入UI动作:为自定义UI控件添加点击事件。
第三步:在布局文件中添加这个自定义控件:
<com.example.uicustomviews.TitleLayout>