zoukankan      html  css  js  c++  java
  • 关于Fragment的使用与多屏幕的设计

    从Android3.0开始,Android引入了Fragment,使得界面能够进行很好的复用;

    Fragment是依附于Activity存在的,单独的Fragment并不能单独显示,而是需要在Activity的布局中进行显示;

    Fragment的用法:

    1、直接在Activity对应布局文件中指定相应的Fragment;

    2、在代码中动态的为Activity的布局添加Fragment;

    第一种用法:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal">
        <fragment android:id="@+id/headlines"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.HeadlinesFragment"
                  android:layout_width="400dp"
                  android:layout_marginRight="10dp"/>
        <fragment android:id="@+id/article"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.ArticleFragment"
                  android:layout_width="fill_parent" />
    </LinearLayout>

    第二种用法:

     if (getSupportFragmentManager().findFragmentByTag(FRAGTAG) == null ) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        MyCloudFragment fragment = new MyCloudFragment();
        transaction.add(fragment, FRAGTAG);
        transaction.commit();
    }

    或者

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    AdapterTransitionFragment fragment = new AdapterTransitionFragment();
    transaction.replace(R.id.sample_content_fragment, fragment);
    transaction.commit();

    前面一种在是布局中增加Fragment,后者是在布局中,使用Fragment替换FrameLayout ;

    Fragment重在复用,下面我们看一下如何设计适应多种屏幕大小的app界面

    设计适应多种屏幕大小的app
     
    1. 使用 wrap_content 和 match_parent
    为了保证你的布局是灵活的而且能够适应不同的屏幕大小的;对于某些视图组件应该使用 wrap_content或者match_parent来适应宽度和高度;
    wrap_content使得视图在高度或者宽度上使用尽可能少的大小来适应内容;
    fill_parent 则会填充到父视图的长度/宽度;
     
    2. 另外一种方式,是使用最小宽度尺寸过滤器(smallest-width),根据不同的屏幕大小,使用不同的layout;例如下面两个layout
     
    res/layout/main.xml   普通版手机布局
     
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment android:id="@+id/headlines"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.HeadlinesFragment"
                  android:layout_width="match_parent" />
    </LinearLayout>
     
    res/layout-sw600dp/main.xml  平板/TV布局(最小屏幕宽度大于600dp的话,会选择这个布局)
     
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal">
        <fragment android:id="@+id/headlines"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.HeadlinesFragment"
                  android:layout_width="400dp"
                  android:layout_marginRight="10dp"/>
        <fragment android:id="@+id/article"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.ArticleFragment"
                  android:layout_width="fill_parent" />
    </LinearLayout>
     
    但是在安卓3.2之前的版本,并不能区分 sw600dp 这种过滤器,而最好使用 layout_large 这种方式;
    但是这样的话,可能会造成两个文件是一模一样的,这样就不好维护,为了解决这个问题,可以使用别的方式
    在layout中,创建一个main_twopanes.xml的这个文件,就是之前的 res/layout-sw600dp/main.xml  这个文件
    然后,在 layout-large/main.xml和layout-sw600dp/main.xml都是一样的
    <resources>
        <item name="main" type="layout">@layout/main_twopanes</item>
    </resources>
     
    这样就使得布局文件更好维护,只需要修改一个文件就行了;
     
    3. 使用横向纵向布局过滤
    res/values/layouts.xml                                          普通版
    res/values-sw600dp-land/layouts.xml                 最小尺寸600dp横向版
    res/values-sw600dp-port/layouts.xml                 最小尺寸600dp纵向版
    res/values-large-land/layouts.xml                       大屏横向版
    res/values-large-port/layouts.xml                        大屏纵向版
     
    4. 使用可拉伸的图标
    在一些场景下,同一个图片再经过了横向,纵向的变化后;或者在不同的屏幕尺寸下,需要展示的大小会不一样,这个时候,使用一个可拉伸的图片就很重要了
    首先准备一个普通的PNG图片,然后使用SDK下的tools/draw9patch.bat 工具,来选择拉伸区域;
     
     
    支持不同的屏幕密度(分辨率)
    使用密度无关的像素
     
    在布局文件里,dp和sp就是这种与pixels无关的单位,他们都是由系统来去自适应相对的宽度的;dp是针对布局的,sp针对的是文字的大小; 
    在布局文件中,应该使用dp/sp,而不要使用px像素这个单位;
     
    提供不同的可选Bitmap
    有以下几种初始格式
    xhdpi: 2.0
    hdpi: 1.5
    mdpi: 1.0 (baseline)
    ldpi: 0.75 
     
    200*200 , 150*150 ,100*100 , 75*75
     
    在res结构中,需要组织成下面这样,不同的目录,使用对应尺寸的图片
     
    MyProject/
      res/
        drawable-xhdpi/
            awesomeimage.png
        drawable-hdpi/
            awesomeimage.png
        drawable-mdpi/
            awesomeimage.png
        drawable-ldpi/
            awesomeimage.png
     
     
    实现自适应的UI流程
    例如,阅读文章的APP的例子,两个视图时候,一个选择文章之后,第二个进行展示;而如果是小屏幕只有一个视图的时候,则显示到另外一个Activity上;
    这就是不同的UI流程;
     
     
    下面是一种判断是是单屏还是双屏显示的方法
     
    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;
        }
    }
     
    一种好的方式是,针对每个视图的操作,都判断其存不存在,因为有可能不在屏幕上显示;
    如下
    Button catButton = (Button) findViewById(R.id.categorybutton);
    OnClickListener listener = /* create your listener here */;
    if (catButton != null) {
        catButton.setOnClickListener(listener);
    }
     
    根据不同的方式,进行不同的流程,如下面是选择一篇文章标题时候的处理流程
     
    @Override
    public void onHeadlineSelected(int index) {
        mArtIndex = index;
        if (mIsDualPane) {
            /* display article on the right pane */
            mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
        } else {
            /* start a separate activity */
            Intent intent = new Intent(this, ArticleActivity.class);
            intent.putExtra("catIndex", mCatIndex);
            intent.putExtra("artIndex", index);
            startActivity(intent);
        }
    }
     
    复用Fragment
     
    在双Fragment的操作时候,布局文件如下
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal">
        <fragment android:id="@+id/headlines"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.HeadlinesFragment"
                  android:layout_width="400dp"
                  android:layout_marginRight="10dp"/>
        <fragment android:id="@+id/article"
                  android:layout_height="fill_parent"
                  android:name="com.example.android.newsreader.ArticleFragment"
                  android:layout_width="fill_parent" />
    </LinearLayout>
     
    在单Fragment的情况下,在ArticleActivity中,可以使用以下代码进行复用
     
    ArticleFragment frag = new ArticleFragment();
    getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
     
    android.R.id.content 是对应的Fragment的布局文件id;
     
    需要注意的是,不要设计耦合程度太高的Activity,这样会使得不好维护;例如应该使用下面的方式进行设计选择文章的操作;
     
    public class HeadlinesFragment extends ListFragment {
        ...
        OnHeadlineSelectedListener mHeadlineSelectedListener = null;
     
        /* Must be implemented by host activity */
        public interface OnHeadlineSelectedListener {
            public void onHeadlineSelected(int index);
        }
        ...
     
        public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
            mHeadlineSelectedListener = listener;
        }
     
        @Override
        public void onItemClick(AdapterView<?> parent,
                                View view, int position, long id) {
            if (null != mHeadlineSelectedListener) {
                mHeadlineSelectedListener.onHeadlineSelected(position);
            }
        }
    }
     
    使用观察者模式,是比较好的解耦方式;
     
    而需要注意的是,在一些横向纵向模式下需要做转换,从单片格到多片格的这种方式的话,由于重新进行渲染,这个时候,我们需要根据情况来进行处理;
    例如下面的代码,就是根据在纵向变成横向之后,单片变多片,需要将文章的Activity给结束掉,返回主Activity去;
     
    public class ArticleActivity extends FragmentActivity {
    int mCatIndex, mArtIndex;
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
     mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
     
     // If should be in two-pane mode, finish to return to main activity
     if (getResources().getBoolean(R.bool.has_two_panes)) {
      finish();
      return;
     }
     ...
    }

    以上文章的内容,大部分是《Android.4.2.documentation-1.6.chm》这个android文档里面的内容,主要是经过了自己的粗略翻译和增加了部分个人理解,水平有限,难免有错误的地方,还望指正;

  • 相关阅读:
    RJ-45与RJ-48的区别
    PCB设计铜铂厚度、线宽和电流关系
    PCB设计铜铂厚度、线宽和电流关系
    WiFi天线对PCB布局布线和结构的要求详解
    WiFi模块选型参考
    掩码是什么意思?
    计算机音频基础-PCM简介
    使用CSS2对页面中的文字添加彩色边框
    SQL Plus
    A Famous Music Composer
  • 原文地址:https://www.cnblogs.com/coldforce/p/4993429.html
Copyright © 2011-2022 走看看