Android移动应用界面的模板化设计

http://www.apkbus.com/android-14578-1-1.html

Android没有像苹果开发那样功能强大的界面开发工具,本身ADT插件提供的界面编辑能力有限,没办法刻画所有的界面情况;Android的界面xml代码可以进行人工修改,而Iphone的全部在图形界面上拖动完成,可没提供任何方式的代码级修改。Android的UI设计开发过程非常繁琐,容易出错,需要很长时间调节界面细节,开发过Android应用的人肯定深有同感。用几年前的网页设计来打个比方,开发Iphone的软件界面就好比是用Frontpage弄点控件拖成一张页面,而开发Android更接近于闭着眼睛在Notepad里一行行的写html标签。为了使开发Android应用更加简便快捷,减少代码冗余,增强软件质量,在咨询行情的开发上我们大量使用了模板化的页面。
思路很简单:将软件里用到的大量重复的页面布局抽象出来,编写成一个抽象的Activity类,然后在实现具体页面时继承它,并且在主内容空白区填入需要的内容。
例如在最近开发的一款资讯类应用中,每张页面上面都有一个顶栏,上面有两个按钮,按钮中间是一行标题文字。按钮上的文字及点击后的功能在每个页面中可能会都不相同。如下图所示的。
1.gif

2011-10-5 16:52 上传
下载附件(11.7 KB)


面对这样一个页面的需求,我们可以设计出一个基本的页面模板AbstractAc1,代码如下所示。

  1. /**
  2. * 通用页面模板1:含上栏,包括左右两个按钮,一个title文字区
  3. * @author zhe.yangz
  4. */ 
  5.   
  6. public class AbstractAc1 extends BaseActivity { 
  7.   
  8.     @Override 
  9.   
  10.     public void onCreate(Bundle savedInstanceState) { 
  11.   
  12.         super.onCreate(savedInstanceState); 
  13.   
  14.         setContentView(R.layout.abac_1); 
  15.   
  16.     } 
  17.   
  18.     /**
  19.      * 设置主内容区域的layoutRes
  20.      * @param layoutResId
  21.      */ 
  22.   
  23.     public void alabSetContentView(int layoutResId) { 
  24.   
  25.         LinearLayout llContent = (LinearLayout) findViewById(R.id.llContent1); 
  26.   
  27.         LayoutInflater inflater = (LayoutInflater) getSystemService( 
  28.   
  29.                 Context.LAYOUT_INFLATER_SERVICE); 
  30.   
  31.         View v = inflater.inflate(layoutResId, null); 
  32.   
  33.         llContent.addView(v); 
  34.   
  35.     } 
  36.   
  37.     /**
  38.      * 隐藏左侧按钮
  39.      */ 
  40.   
  41.     public void alabHideButtonLeft(boolean bSetHide) { 
  42.   
  43.         Button bt = alabGetButtonLeft(); 
  44.   
  45.         if (null != bt) { 
  46.   
  47.             if (bSetHide) bt.setVisibility(View.INVISIBLE); 
  48.   
  49.             else bt.setVisibility(View.VISIBLE); 
  50.   
  51.         } 
  52.   
  53.     } 
  54.   
  55.     /**
  56.      * 隐藏右侧按钮
  57.      */ 
  58.   
  59.     public void alabHideButtonRight(boolean bSetHide) { 
  60.   
  61.         Button bt = alabGetButtonRight(); 
  62.   
  63.         if (null != bt) { 
  64.   
  65.             if (bSetHide) bt.setVisibility(View.INVISIBLE); 
  66.   
  67.             else bt.setVisibility(View.VISIBLE); 
  68.   
  69.         } 
  70.   
  71.     } 
  72.   
  73.     /**
  74.      * 得到模板上导航栏的左侧按钮,一般为[返回]
  75.      * @return 成功则返回Button对象,失败则返回null。
  76.      */ 
  77.   
  78.     public Button alabGetButtonLeft() { 
  79.   
  80.         return (Button) findViewById(R.id.btBack1); 
  81.   
  82.     } 
  83.   
  84.     /**
  85.      * 得到模板上导航栏的右侧按钮,一般为[刷新]
  86.      * @return 成功则返回Button对象,失败则返回null。
  87.      */ 
  88.   
  89.     public Button alabGetButtonRight() { 
  90.   
  91.         return (Button) findViewById(R.id.btRefresh1); 
  92.   
  93.     } 
  94.   
  95.     /**
  96.      * 设置模板上导航栏中间的标题文字
  97.      * @param titleText
  98.      * @return 修改成功返回true,失败返回false
  99.      */ 
  100.   
  101.     public boolean alabSetBarTitleText(String titleText) { 
  102.   
  103.         TextView tv = (TextView) findViewById(R.id.txBarTitle1); 
  104.   
  105.         if (null != tv) { 
  106.   
  107.             tv.setText(titleText); 
  108.   
  109.             return true
  110.   
  111.         } 
  112.   
  113.         return false
  114.   
  115.     } 
  116.   
  117.   
/**
 
* 通用页面模板1:含上栏,包括左右两个按钮,一个title文字区
 
* @author zhe.yangz
 
*/
 
public class AbstractAc1 extends BaseActivity {
 
    @Override
 
    public void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.abac_1);
 
    }
 
    /**
 
     * 设置主内容区域的layoutRes
 
     * @param layoutResId
 
     */
 
    public void alabSetContentView(int layoutResId) {
 
        LinearLayout llContent = (LinearLayout) findViewById(R.id.llContent1);
 
        LayoutInflater inflater = (LayoutInflater) getSystemService(
 
                Context.LAYOUT_INFLATER_SERVICE);
 
        View v = inflater.inflate(layoutResId, null);
 
        llContent.addView(v);
 
    }
 
    /**
 
     * 隐藏左侧按钮
 
     */
 
    public void alabHideButtonLeft(boolean bSetHide) {
 
        Button bt = alabGetButtonLeft();
 
        if (null != bt) {
 
            if (bSetHide) bt.setVisibility(View.INVISIBLE);
 
            else bt.setVisibility(View.VISIBLE);
 
        }
 
    }
 
    /**
 
     * 隐藏右侧按钮
 
     */
 
    public void alabHideButtonRight(boolean bSetHide) {
 
        Button bt = alabGetButtonRight();
 
        if (null != bt) {
 
            if (bSetHide) bt.setVisibility(View.INVISIBLE);
 
            else bt.setVisibility(View.VISIBLE);
 
        }
 
    }
 
    /**
 
     * 得到模板上导航栏的左侧按钮,一般为[返回]
 
     * @return 成功则返回Button对象,失败则返回null。
 
     */
 
    public Button alabGetButtonLeft() {
 
        return (Button) findViewById(R.id.btBack1);
 
    }
 
    /**
 
     * 得到模板上导航栏的右侧按钮,一般为[刷新]
 
     * @return 成功则返回Button对象,失败则返回null。
 
     */
 
    public Button alabGetButtonRight() {
 
        return (Button) findViewById(R.id.btRefresh1);
 
    }
 
    /**
 
     * 设置模板上导航栏中间的标题文字
 
     * @param titleText
 
     * @return 修改成功返回true,失败返回false
 
     */
 
    public boolean alabSetBarTitleText(String titleText) {
 
        TextView tv = (TextView) findViewById(R.id.txBarTitle1);
 
        if (null != tv) {
 
            tv.setText(titleText);
 
            return true;
 
        }
 
        return false;
 
    }
 
}
 


我们创建了一张模板页面,然后在应用中的实际页面继承于它。这样,每张继承的页面都可以拥有类似的顶栏布局,并且代码简洁。下面就是继承的例子。


  1. /**
  2. * 样例页面
  3. * @author zhe.yangz
  4. */ 
  5.   
  6. public class HomeActivity extends AbstractAc1 { 
  7.   
  8.     @Override 
  9.   
  10.     public void onCreate(Bundle savedInstanceState) { 
  11.   
  12.         super.onCreate(savedInstanceState); 
  13.   
  14.         alabSetContentView(R.layout.ac_home); 
  15.   
  16.         setTopBarAndAction(); 
  17.   
  18.     } 
  19.   
  20.     private void setTopBarAndAction() { 
  21.   
  22.         alabSetBarTitleText("TEST HOME"); // 设置Title标题 
  23.   
  24.         alabGetButtonLeft().setText("LeftBt"); // 设置左按钮上的文字 
  25.   
  26.         alabGetButtonRight().setText("RightBt"); // 设置右按钮上的文字 
  27.   
  28.         alabGetButtonRight().setOnClickListener(new OnClickListener() { 
  29.   
  30.             @Override 
  31.   
  32.             public void onClick(View v) { 
  33.   
  34.                 // 按钮执行事件 
  35.   
  36.                 // ... 
  37.   
  38.             } 
  39.   
  40.         }); 
  41.   
  42.     } 
  43.   
  44.   
/**
 
* 样例页面
 
* @author zhe.yangz
 
*/
 
public class HomeActivity extends AbstractAc1 {
 
    @Override
 
    public void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        alabSetContentView(R.layout.ac_home);
 
        setTopBarAndAction();
 
    }
 
    private void setTopBarAndAction() {
 
        alabSetBarTitleText("TEST HOME"); // 设置Title标题
 
        alabGetButtonLeft().setText("LeftBt"); // 设置左按钮上的文字
 
        alabGetButtonRight().setText("RightBt"); // 设置右按钮上的文字
 
        alabGetButtonRight().setOnClickListener(new OnClickListener() {
 
            @Override
 
            public void onClick(View v) {
 
                // 按钮执行事件
 
                // ...
 
            }
 
        });
 
    }
 
}
 


就完成了一张具有如下顶栏效果的页面,页面的背景、按钮配色等效果在AbstractAc1中定义。
2.gif

2011-10-5 16:52 上传
下载附件(5.19 KB)

alabSetContentView()是在AbstractAc1中定义的方法,在衍生类中调用该方法,传入一个界面定义xml,方法中实现了使用LayoutInflater生成view,使得这个页面中定义的主内容区的界面xml会和原来AbstractAc1的界面xml合并在一起,成为一个完整的页面。有些情况下,左右按钮可以单独或一起隐藏,可以使用AbstractAc1中定义的alabHideButtonLeft和alabHideButtonRight进行设置。
使用模板化方式开发界面,目前我们开发的Android应用中的Activity的层次结构大致如下。
3.gif

2011-10-5 16:52 上传
下载附件(5.01 KB)


这样模板化的页面探索的实践被用在我们目前Android应用开发中。大致估计一下,界面代码比原来减少40%,减少了冗余,也间接提高了软件质量和可维护性,极大提升了业务需求变化带来的快速反应能力。接下去我们希望能够继续深入探索,找到更多的提升移动软件界面开发效率和质量的方法,也希望有好想法的同学和我们深入交流,共同探讨,博采众长。

补充:
文中模板1中所用的布局定义文件abac_1.xml忘给出了,代码如下,

  1. <?xml version="1.0" encoding="utf-8"?> 
  2.   
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  4.   
  5.         android:orientation="vertical" android:layout_width="fill_parent" 
  6.   
  7.         android:layout_height="fill_parent" android:background="@color/section_bgcolor"
  8.   
  9.         <!-- 顶栏 --> 
  10.   
  11.         <LinearLayout 
  12.   
  13.                 android:layout_width="fill_parent" 
  14.   
  15.                 android:layout_height="43dp" 
  16.   
  17.                 android:padding="5dp" 
  18.   
  19.                 android:background="@drawable/topbar_bg"  
  20.                 android:orientation="horizontal"  
  21.                 android:gravity="center"
  22.   
  23.                 <Button style="@style/AliBt" mce_style="@style/AliBt" 
  24.   
  25.                         android:id="@+id/btLeft"  
  26.                         android:text="Left" /> 
  27.   
  28.                 <Spinner android:id="@+id/sp_HY" 
  29.   
  30.                         android:visibility="invisible" 
  31.   
  32.                         android:layout_width="0dp" 
  33.   
  34.                         android:layout_height="0dp"/> 
  35.   
  36.                 <TextView style="@style/AliBarTitle" mce_style="@style/AliBarTitle" 
  37.   
  38.                         android:id="@+id/txBarTitle1"  
  39.                         android:text="" /> 
  40.   
  41.                 <Button style="@style/AliBt" mce_style="@style/AliBt" 
  42.   
  43.                         android:id="@+id/btRight"  
  44.                         android:text="Right" /> 
  45.   
  46.         </LinearLayout> 
  47.   
  48.         <!-- 主内容框架 --> 
  49.   
  50.         <LinearLayout 
  51.   
  52.                 android:id="@+id/llContent1" 
  53.   
  54.                 android:orientation="vertical" 
  55.   
  56.                 android:layout_width="fill_parent" 
  57.   
  58.                 android:layout_height="0dp" 
  59.   
  60.                 android:layout_weight="1"
  61.   
  62.         </LinearLayout> 
  63.   
  64.          
  65. </LinearLayout> 
  66.   
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值