二、Android中,可以将某块自定义的UI从layout.xml中实例化出来使用,使用的是LayoutInflater,基于该技术,我们可以换一种思路来解决这个问题:写页面layout文件的时候不用关心底部菜单。然后在展示的代码中,定义一个大的视图页面将页面的layout文件以及底部菜单的layout包含进来,过程如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lAONrIje-1638076594364)(http://hi.csdn.net/attachment/201110/21/0_1319200116JAjZ.gif)]
详细设计
1. 设计大的视图页面layout:bottom_menu_layout.xml,该页面用来包含以后自定义的业务页面,以及底部菜单。
<?xml version="1.0"encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<LinearLayout android:orientation="horizontal"android:layout_width="fill_parent" android:gravity="bottom" android:layout_height="wrap_content" android:id="@+id/bottom_menu_button_group_id"> </LinearLayout> </LinearLayout> |
2. 设计底部菜单按钮layout:bottom_menu_button_frame.xml,该页面用来定义每一个按钮的样式,一般需要包含一个位于上方的图片以及一个位于下方的按钮文字。
<?xml version="1.0"encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="64px" android:layout_height="wrap_content" android:id="@+id/bottom_menu_template_button_id" android:background="@drawable/tab_one_normal"> <ImageView android:id="@+id/bottom_menu_template_img_id" android:paddingTop="5px"android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content"android:src="@drawable/image" /> <TextView android:layout_width="wrap_content"android:id="@+id/bottom_menu_template_text_id" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:textSize="11sp"android:paddingBottom="5px" /> </LinearLayout> |
3. 自定义封装按钮的JAVA类:BottomButton,封装底部菜单按钮的基本信息:图片、文字、按钮事件、是否当前被选中的按钮等。
public class BottomButton { // 按钮菜单文字 private String text;
// 按钮菜单图片 private int backgroundResource;
// 点击事件。 private View.OnClickListener clickListener;
// 是否当前已经选中的按钮,如果是则高亮,并且忽略点击事件。 private boolean isCurrent = false; } |
4. 自定义底部菜单Layout 类:BottomMenuLayout,该类继承自LinearLayout,用来处理按钮的展示,该类负责以下三件事情:
a) 将底部菜单layout加入到整个大视图页面中。
b) 绑定每一个菜单按钮。
c) 重新计算整个布局的大小,将菜单固定在底部。
public class BottomMenuLayout extends LinearLayout {
//实例化layout使用的类 private LayoutInflater mInflater;
//保存菜单按钮的集合,每一个集合元素代表一个按钮,包含了按钮所需要的信息:图片,文字,按键处理事件。 private List<BottomButton> bottomButtons;
//封装菜单按钮的布局。 private View bottomMenuLayout;
public void processInitButton() { //初始化布局,将底部菜单layout加入到视图中。 initLayout(this.getContext());
//绑定每一个菜单按钮 bindingButton( |
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
);
//重新计算整个布局的大小,使用整个屏幕的高度减去底部菜单的高度,
//得出并设置中间页面部分的高度,就能够将菜单固定在底部。
resizeLayout();
}
注:这里屏蔽了实现细节,具体参考附件代码。
5. 当以上每一个零散的部分都完成以后,就需要一个组装者,来负责将各个部分组装在一起,使之能够正常运作起来,这里定义一个继承自Activity的类:BaseBottomMenuActivity ,用来充当组装者的角色,开发业务时需要更改方式,原来直接继承自Activity的类改为继承该类。该类主要完成以下工作:
a) 创建出整个大视图页面。
b) 创建出中间内容部分页面,也就是由开发者定义的实际layout内容。并加到整个大视图的页面中来。
c) 创建出底部菜单,并将底部菜单加入到整个大视图的页面中来。
d) 需要得知子类继承该类后,具体使用的layout页面的ID,定义抽象方法由子类实现以提供该ID。
e) 需要得知子类继承该类后,具体需要哪些菜单按钮,定义抽象方法由子类实现以提供按钮的列表。
f) 需要得知子类继承该类后,还需要做哪些页面初始化的工作,定义抽象方法由子类实现以便在页面初始过程中调用。
public abstract class BaseBottomMenuActivity extends Activity { private LayoutInflater mInflater; //实例化layout使用的类 protected BottomMenuLayout bottomMenuLayout; //底部菜单UI部分 protected View contentView; //页面中间UI部分
final protected void onCreate(Bundle savedInstanceState) { //a) 创建出整个大视图页面。 //b) 创建出中间内容部分页面,也就是由开发者定义的实际layout内容。并加到整个大视图的页面中来。 //c) 创建出底部菜单,并将底部菜单加入到整个大视图的页面中来。 }
/** * 子类实现后,在原来的onCreate方法中内容移到这里来操作。 * @paramsavedInstanceState */ protected abstract void onCreatOverride(Bundle savedInstanceState);
/** * 返回layout xml的ID * 原本在Activity的onCreate方法中调用的setContentView(R.layout.xxxxLayoutId); 现在从该方法返回。 * @return */ public abstract int getContentViewLayoutResId();
/** * 创建底部菜单,需要子类实现,在此方法中, * 创建多个BottomButton对象并放置到List中返回即可。 * 如果需要哪一个按钮当前被选中,则设置BottomButton的isCurrent属性为ture. * @param bottomButtons * @param bottomMenuLayout * @return */ public abstractList<BottomButton> getButtonList(); |
注:这里屏蔽了实现细节,具体参考附件代码。
实现及使用
具体实现代码见附件。
在上述设计的各部分都实现后,就可以进行使用了,使用时,与平常开发正常页面的步骤一样,首先画layout.xml,然后定义activity,进行绑定并配置AndroidManifest.xml文件,不同的地方在于定义的Activity需要继承BaseBottomMenuActivity。并且根据以下步骤开发该Activity:
1. 在子类中继承实现getButtonList方法,在方法中封装BottomButton对象返回,每一个BottomButton代表一个菜单项,具体属性见BottomButton定义。 2. 在子类中继承实现getContentViewLayoutResId方法,返回layout xml的ID。 3. 在子类中继承实现onCreatOverride方法,原先在onCreat方法中完成的事情挪到这里,super.onCreate(savedInstanceState);和setContentView就不需要调用了。 |
测试
让我们来写一个简单的Demo来进行测试,该Demo中,除了底部菜单,只有一个TextView文本,该类继承了BaseBottomMenuActivity:
ntView就不需要调用了。
测试
让我们来写一个简单的Demo来进行测试,该Demo中,除了底部菜单,只有一个TextView文本,该类继承了BaseBottomMenuActivity: