summaryrefslogtreecommitdiffstats
path: root/docs/html/intl/zh-CN/training/multiscreen/adaptui.jd
blob: 89908fe46ef9b14962eba8832d3bbe4d0a7fdc82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
page.title=实施自适应用户界面流程
parent.title=针对多种屏幕进行设计
parent.link=index.html

trainingnavtop=true
previous.title=支持各种屏幕密度
previous.link=screendensities.html

@jd:body


<!-- This is the training bar -->
<div id="tb-wrapper"> 
<div id="tb"> 
 
<h2>本教程将指导您</h2>

<ol>
  <li><a href="#TaskDetermineCurLayout">确定当前布局</a></li>
  <li><a href="#TaskReactToLayout">根据当前布局做出响应</a></li>
  <li><a href="#TaskReuseFrag">重复使用其他活动中的片段</a></li>
  <li><a href="#TaskHandleConfigChanges">处理屏幕配置变化</a></li>
</ol>

<h2>您还应参阅</h2>

<ul>
  <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">支持平板电脑和手持设备</a></li>
</ul>
 
<h2>试试看</h2>
 
<div class="download-box">
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">下载示例应用</a>
<p class="filename">NewsReader.zip</p> 
</div> 
 
 
</div> 
</div> 

<p>根据您的应用当前显示的布局,用户界面流程可能会有所不同。例如,如果您的应用处于双面板模式下,点击左侧面板上的项即可直接在右侧面板上显示相关内容;如果该应用处于单面板模式下,相关内容就应以其他活动的形式在同一面板上显示。</p>


<h2 id="TaskDetermineCurLayout">确定当前布局</h2>

<p>由于每种布局的实施都会稍有不同,因此您可能需要先确定当前向用户显示的布局。例如,您可以了解用户所处的是“单面板”模式还是“双面板”模式。要做到这一点,您可以查询指定视图是否存在以及是否已显示出来。</p>

<pre class="prettyprint">
public class NewsReaderActivity extends FragmentActivity {
    boolean mIsDualPane;

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

        View articleView = findViewById(R.id.article);
        mIsDualPane = articleView != null &amp;&amp; 
                        articleView.getVisibility() == View.VISIBLE;
    }
}
</pre>

<p>请注意,这段代码用于查询“报道”面板是否可用,与针对具体布局的硬编码查询相比,这段代码的灵活性要大得多。</p>

<p>再举一个适应各种组件的存在情况的方法示例:在对这些组件执行操作前先查看它们是否可用。例如,新闻阅读器示例应用中有一个用于打开菜单的按钮,但只有在版本低于 3.0 的 Android 上运行该应用时,这个按钮才会存在,因为 API 级别 11 或更高级别中的  <PH>{@link android.app.ActionBar}</PH>  已取代了该按钮的功能。因此,您可以使用以下代码为此按钮添加事件侦听器:</p>

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


<h2 id="TaskReactToLayout">根据当前布局做出响应</h2>

<p>有些操作可能会因当前的具体布局而产生不同的结果。例如,在新闻阅读器示例中,如果用户界面处于双面板模式下,那么点击标题列表中的标题就会在右侧面板中打开相应报道;但如果用户界面处于单面板模式下,那么上述操作就会启动一个独立活动:</p>

<pre>
&#64;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);
    }
}
</pre>

<p>同样,如果该应用处于双面板模式下,就应设置带导航标签的操作栏;但如果该应用处于单面板模式下,就应使用旋转窗口小部件设置导航栏。因此您的代码还应确定哪种情况比较合适:</p>

<pre>
final String CATEGORIES[] = { "热门报道", "政治", "经济", "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 &lt; 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<String>(this, 
                R.layout.headline_item, CATEGORIES);
        actionBar.setListNavigationCallbacks(adap, handler);
    }
}
</pre>


<h2 id="TaskReuseFrag">重复使用其他活动中的片段</h2>

<p>多屏幕设计中的重复模式是指,对于某些屏幕配置,已实施界面的一部分会用作面板;但对于其他配置,这部分就会以独立活动的形式存在。例如,在新闻阅读器示例中,对于较大的屏幕,新闻报道文本会显示在右侧面板中;但对于较小的屏幕,这些文本就会以独立活动的形式存在。</p>

<p>在类似情况下,您通常可以在多个活动中重复使用相同的  <PH>{@link android.app.Fragment}</PH>  子类以避免代码重复。例如,您在双面板布局中使用了 <code>ArticleFragment</code>:</p>

{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}

<p>然后又在小屏幕的活动布局中重复使用(无布局)了它 (<code>ArticleActivity</code>):</p>

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

<p>当然,这与在 XML 布局中声明片段的效果是一样的,但在这种情况下却没必要使用 XML 布局,因为报道片段是此活动中的唯一组件。</p>

<p>请务必在设计片段时注意,不要针对具体活动创建强耦合。要做到这一点,您通常可以定义一个界面,该界面概括了相关片段与其主活动交互所需的全部方式,然后让主活动实施该界面:</p>

<p>例如,新闻阅读器应用的 <code>HeadlinesFragment</code> 会精确执行以下代码:</p>

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

<p>然后,如果用户选择某个标题,相关片段就会通知由主活动指定的侦听器(而不是通知某个硬编码的具体活动):</p>

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

<p><a
href="{@docRoot}guide/practices/tablets-and-handsets.html">支持平板电脑和手持设备</a>的指南中进一步介绍了此技术。</p>


<h2 id="TaskHandleConfigChanges">处理屏幕配置变化</h2>

<p>如果您使用独立活动实施界面的独立部分,那么请注意,您可能需要对特定配置变化(例如屏幕方向的变化)做出响应,以便保持界面的一致性。</p>

<p>例如,在运行 Android 3.0 或更高版本的标准 7 英寸平板电脑上,如果新闻阅读器示例应用运行在纵向模式下,就会在使用独立活动显示新闻报道;但如果该应用运行在横向模式下,就会使用双面板布局。</p>

<p>也就是说,如果用户处于纵向模式下且屏幕上显示的是用于阅读报道的活动,那么您就需要在检测到屏幕方向变化(变成横向模式)后执行相应操作,即停止上述活动并返回主活动,以便在双面板布局中显示相关内容:</p>

<pre>
public class ArticleActivity extends FragmentActivity {
    int mCatIndex, mArtIndex;

    &#64;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;
        }
        ...
}
</pre>