Android官方开发文档Training系列课程中文版:多样屏幕之实现自适应UI

简介: 原文地址:http://android.xsoftlab.net/training/multiscreen/adaptui.html基于程序当前所显示的布局来说,UI流程可能会有所不同。

原文地址:http://android.xsoftlab.net/training/multiscreen/adaptui.html

基于程序当前所显示的布局来说,UI流程可能会有所不同。比如说,如果程序当前处于多面板模式,点击左面板中的项目会直接在右面版中显示具体的内容;如果当前是单面板模式,那么具体的内容则会在新的页面中显示。

检查当前的布局

因为每种布局的实现可能会有所不同,所以首先要做的事情就是检查用户当前使用的是哪种布局。比如说,你可能需要知道用户当前处于”单面板”模式还是”多面板”模式。你可以通过查询给定的View是否存在及是否可见的方式来得知当前的模式。

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;
    }
}

注意这部分代码在查询”article”面板是否可用,这要比查询指定布局的方式要灵活的多。

如何适配不同的组件的另一个示例是通过检查这些组件是否可用的方式来完成的。比如说,在新闻阅读APP中,有一个用于打开菜单的按钮,但是这个按钮只在3.0以上的版本才有。所以,如果要为这个按钮添加监听器,你可以这么做:

Button catButton = (Button) findViewById(R.id.categorybutton);
OnClickListener listener = /* create your listener here */;
if (catButton != null) {
    catButton.setOnClickListener(listener);
}

根据当前的布局做出响应

一些行为可能基于当前的布局产生不同的结果。比如说,在新闻阅读APP中,点击任意一条新闻标题,在多面板模式中,具体文章则会出现在右面板中,但是在单面板模式中,则会启动一个新的Activity来显示这些文章。

@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);
    }
}

同样的,如果APP当前处于多面板模式,那么应该设置带有tab的ActionBar用于导航,然而,在单面板模式下,就应当设置带有spinner的导航控件。所以代码中还应当检查当前是哪种情况:

final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };
public void onCreate(Bundle savedInstanceState) {
    ....
    if (mIsDualPane) {
        /* use tabs for navigation */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
        int i;
        for (i = 0; i < CATEGORIES.length; i++) {
            actionBar.addTab(actionBar.newTab().setText(
                CATEGORIES[i]).setTabListener(handler));
        }
        actionBar.setSelectedNavigationItem(selTab);
    }
    else {
        /* use list navigation (spinner) */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
        SpinnerAdapter adap = new ArrayAdapter(this, 
                R.layout.headline_item, CATEGORIES);
        actionBar.setListNavigationCallbacks(adap, handler);
    }
}

重用Fragment

在设计多面板的应用时会反复出现的一个场景,有一部分UI在一种屏幕配置中以面板的形式出现,而在其它的配置中,又是以独立的Activity出现。

在类似这种情况下,你可以通过重用Fragment的方式来避免代码冗余。比如,ArticleFragment就用于多面板的情况:

<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>

在小屏幕中,又被Activity重用:

ArticleFragment frag = new ArticleFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();

上面的代码与在XML布局中声明Fragment含有相同的效果,但是这种情况下XML布局就没必要工作了,因为article Fragment作为了这个Activity的组件。

一个非常重要的点要记住,在设计Fragment时不要与指定的Activity产生强耦合。你可以通过定义接口的方式来使Fragment与宿主Activity产生交互,宿主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;
    }
}

因此,当用户选择了一条新闻时,Fragment通过接口的方式来通知宿主Activity:

public class HeadlinesFragment extends ListFragment {
    ...
    @Override
    public void onItemClick(AdapterView<?> parent, 
                            View view, int position, long id) {
        if (null != mHeadlineSelectedListener) {
            mHeadlineSelectedListener.onHeadlineSelected(position);
        }
    }
    ...
}

处理屏幕配置变更

如果使用了单独的Activity实现了UI的独立部分,那么要记得响应某些配置的变化,比如屏幕旋转,以便保持UI的一致性。

比如说,一款运行Android 3.0系统的7英寸平板,新闻阅读APP在垂直模式下使用的是独立的Activity展示文章的内容,但是在水平模式下使用的是多面板模式。

如果用户当前处于垂直模式下,那么需要检查方向更改为了水平模式,并需要通过结束结尾Activity并返回MainActivity的方式来让内容展示于双面板模式:

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;
        }
        ...
}
目录
相关文章
|
7月前
|
编解码 人工智能 自然语言处理
让大模型理解手机屏幕,苹果多模态Ferret-UI用自然语言操控手机
【5月更文挑战第29天】苹果推出Ferret-UI,一个结合图像识别和自然语言处理的多模态大语言模型,允许用户通过自然语言指令操控手机。该系统能适应不同屏幕布局,识别UI元素并执行相应操作,有望变革手机交互方式,提升无障碍体验,并在测试和开发中发挥作用。但需面对屏幕多样性及准确性挑战。[论文链接](https://arxiv.org/pdf/2404.05719.pdf)
183 3
|
7月前
|
存储 XML 编译器
【Android 从入门到出门】第二章:使用声明式UI创建屏幕并探索组合原则
【Android 从入门到出门】第二章:使用声明式UI创建屏幕并探索组合原则
144 3
|
Android开发
android 修改UI默认屏幕方向
android 修改UI默认屏幕方向
233 0
|
Android开发
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(二)
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(二)
429 0
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(二)
|
编解码 Android开发
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(一)
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(一)
533 0
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(一)
|
Android开发
Android屏幕适配之状态栏导航栏半透明、全透明(5.0以上去阴影),方法多样
1.1 StatusBar半透明用StatusBarView实现(4.4以上有效) 1.2 StatusBar半透明用setStatusBarColor实现(5.0以上有效) 2.1 StatusBar全透明用fitSystemWindows实现(4.
4951 0
|
Android开发 索引 Java
Android NestedScrollView/ScrollView包裹ViewPager自适应高度
Android NestedScrollView/ScrollView包裹ViewPager自适应高度 当Android的NestedScrollView/ScrollView这类滚动View包裹ViewPager时候,V...
3980 0
|
Android开发 数据格式 XML
Android项目实战(五):TextView自适应大小
原文:Android项目实战(五):TextView自适应大小 对于设置TextView的字体默认大小对于UI界面的好看程度是很重要的,小屏幕设置的文字过大或者大屏幕设置的文字过小都造成UI的不美观   现在就让我们学习自适应大小的TextView控件,即当文字长度变化时,文字的大小会相应的变化...
912 0
|
Android开发 数据格式 XML
Android谷歌官方的自适应TextView字体大小的解决方案
Android谷歌官方的自适应TextView字体大小的解决方案 有时候UI限定了TextView宽度或者布局的控件空间尺寸不足,而此时的TextView里面的文本就无法完全正常显示。
3132 0
|
Android开发 数据格式 XML
Android弹性收缩自适应布局FlexboxLayout
Android弹性收缩自适应布局FlexboxLayout 其在github上的项目主页:https://github.com/google/flexbox-layout 使用前先添加引用: dependencies { implementation 'com.
2683 0
下一篇
DataWorks