Android响应式界面开发要点

现在很多项目需要到达同一个Apk既可以在Phone上跑也尅在tablet上跑,即界面要适应不同尺寸和类型的需要而自动调整。这个即为响应式设计。在web开发商响应式设计已经是个常谈的内容了,而对于android开发,也有很多相关的资料,比如使用fragment。这里将一些要点总结下。

 

1. 使用relativelayout和wrap_content、match_parent标记

2. 建立多Layout文件

     API > 3.2可以将小屏幕文件放到res/layout/main.xml,大屏幕文件放到res/layout-sw600dp/main.xlm

     API<3.2同时提供对老版本的支持,将大屏幕布局文件放到res/layout-large/main.xml

     

     或者用资源别名:

     

这样子可以直接用:

setContentView(R.layout.main)

参考:http://wen66.iteye.com/blog/1161375

 

3. 提供多套图片资源文件

 

4. 提供多套启动图标放置到mipmap文件夹(而不是drawable文件夹),以免在高分辨率的屏幕上出现launcher图表模糊的情况

     

 

5. 宿主activity在setcontentview后通过查询某个view(多pane中必须出现的view)是否存在而判定当前是多pane还是单pane状态:     

public class NewsReaderActivity extends FragmentActivity {
    boolean mIsDualPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        View articleView = findViewById(R.id.article);
        mIsDualPane = articleView != null &&
                articleView.getVisibility() == View.VISIBLE;
    }
}

  获得这个mIsDualPane变量的值后即可以在运行时决定是刷新second pane(多pane中原本需要在单pane中另起activity展示的那个fragment)还是起新的activity:

 

 

 

6. 操作内容的代码尽量放到fragment中,和activity解耦合,同时可以提供fragment的重用性

    比如,两个fragment单独写成类, 在多pane中,可以布局成:

   

  单pane中可以将当前的fragment的替换:

   

 

7. 使用EventBus

    通常多pane的设计中,比如Fragment A是个Headline,Fragement B是detail,那么B通常需要实现A的点击事件的接口,这样子的话,两个fragment就高耦合了,而且需要在Fragment A中编写一个interface,如果Fragment很多,情景更复杂些,就乱了。

 

这里可以使用EventBus这个框架,一个典型的发布者-订阅者模式。具体可以参考:

https://github.com/greenrobot/EventBus

 

使用方法大致如下:

a. 首先定义自己的Event,这里其实是随便写个类,例子中Headline需传一个点击时候的listview的position给Detail fragment,所以可以写个包装int类型的messageevent:

public class MessageEvent {

    public int positioin;

    public MessageEvent(int positioin) {
        this.positioin = positioin;
    }
}

 

b.  在订阅者(即Detail fragment或者说fragment B)中,onstart和onstop要注册/解注册:

@Override
public void onStart() {
    super.onStart();;
    EventBus.getDefault().register(this);
}

@Override
public void onStart() {
    super.onStart();
    setNewsCategory(0);
    EventBus.getDefault().register(this);
}

 

c. 在订阅者(即Detail fragment或者说fragment B)中,写一个名字叫onEvent的函数,带回来的参数是MessageEvent类型,这个函数即被调用的方法,等待Headline传过来包装了position数据的MessageEvent对象

public void onEvent(MessageEvent event){
    int index = event.positioin;
   // do something using index
}

 

d. 在发布者(即Headline Fragment或者说Fragment A)中,在合适的地方执行post,这里即在listview被点击的回调中发送post:

@Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        EventBus.getDefault().post(new MessageEvent(position));
    }

 

大功告成,这里可以发现两个fragment没有写任何的interface也没implements任何的接口,也不用实例化一个listenser并且setonlistener。

这里的原理大致是,EventBus在某个组件中注册的时候回记录下这个组件里面的onEvent函数,一个应用中可能有多个onEvent函数等待被调用,这里即通过onEvent函数的参数类型和个数来区别。

 

关于EventBus更多使用方法可以参考

https://github.com/greenrobot/EventBus/blob/master/HOWTO.md

 

 

 

posted @ 2015-06-30 14:54  soaringEveryday  阅读(2190)  评论(0编辑  收藏  举报