预览一下效果:
素材:
新建一个布局title_bar.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="@color/colorTitle" android:orientation="horizontal"> <Button android: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" /> <TextView android: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" /> <Button android: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="http://schemas.android.com/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{ @Override protected 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="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.example.uicustomviews.TitleLayout android: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() { @Override public void onClick(View v) { //结束当前Activity ((Activity) getContext()).finish(); } }); titleEdit.setOnClickListener(new OnClickListener() { @Override public 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>