我正在尝试使我的应用程序适应 Adaptative UI Flows 示例,但我遗漏了一些东西,我不知道它是什么。正如您将在下面看到的,NewsListFragment 加载其布局取决于设备是处于纵向还是横向模式,并且由于我没有手动处理配置更改,因此从纵向到横向会更改此类布局。
预期行为:当布局为纵向时,仅显示列表。当布局为横向时,同时显示列表和 web 视图。
实际行为:当布局为纵向时,仅显示列表。但是,当布局为横向时,NewsListFragment 消失了,这似乎没有任何意义,因为我为它设置了固定宽度,并且它的高度设置为 match_parent。
新闻列表片段:
公共类 NewsListFragment 扩展 ListFragment 实现 OnRefreshListener {
private static PullToRefreshLayout mPullToRefreshLayout;
private NewsFragmentArrayAdapter listAdapter;
private NewsFeedProvider newsFeedProvider;
private NewsListFragmentListener mCallback;
/**
* Called to do initial creation of a fragment. This is called after
* {@link #onAttach(android.app.Activity)} and before
* {@link #onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)}.
* <p/>
* <p>Note that this can be called while the fragment's activity is
* still in the process of being created. As such, you can not rely
* on things like the activity's content view hierarchy being initialized
* at this point. If you want to do work once the activity itself is
* created, see {@link #onActivityCreated(android.os.Bundle)}.
*
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (listAdapter == null) {
listAdapter = new NewsFragmentArrayAdapter(getActivity());
setListAdapter(listAdapter);
}
if (newsFeedProvider == null) {
newsFeedProvider = new NewsFeedProvider(getActivity());
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
getListView().setItemChecked(position, Boolean.TRUE);
mCallback.onNewsArticleSelected(position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (NewsListFragmentListener) activity;
}
catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement NewsListFragmentListener");
}
((NewsReaderActivity) activity).onSectionAttached(
new ArrayList<>(
Arrays.asList(
Utils.getStringArray(
getActivity().getApplicationContext(),
"navigation_drawer_items", new String[]{""})
)
).indexOf(Utils.getString(getActivity().getApplicationContext(), "title_section1",
"Home"))
);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View ret = inflater.inflate(R.layout.fragment_news_feed, container, false);
listAdapter.updateShownNews();
return ret;
}
/**
* Attach to list view once the view hierarchy has been created.
*
* @param view
* @param savedInstanceState
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// This is the View which is created by ListFragment
ViewGroup viewGroup = (ViewGroup) view;
// We need to create a PullToRefreshLayout manually
mPullToRefreshLayout = new PullToRefreshLayout(viewGroup.getContext());
Options.Builder optionsBuilder = Options.create();
int retrieved = Utils.getInt(getActivity(), "feed_refresh_distance_percentage",
R.integer.feed_refresh_distance_percentage);
float scrollDistance = (float) retrieved / 100;
optionsBuilder = optionsBuilder
.scrollDistance(scrollDistance);
optionsBuilder = optionsBuilder.headerTransformer(new TranslatableHeaderTransformer());
// We can now setup the PullToRefreshLayout
ActionBarPullToRefresh.from(getActivity())
// We need to insert the PullToRefreshLayout into the Fragment's ViewGroup
.insertLayoutInto(viewGroup)
// We need to mark the ListView and its empty view as pullable
// This is because they are not direct children of the ViewGroup
.theseChildrenArePullable(getListView(), getListView().getEmptyView())
// Set the OnRefreshListener
.listener(this).useViewDelegate(ImageView.class, new ViewDelegate() {
@Override
public boolean isReadyForPull(View view, float v, float v2) {
return Boolean.TRUE;
}
}).options(optionsBuilder.build())
// Finally commit the setup to our PullToRefreshLayout
.setup(mPullToRefreshLayout);
getListView().setChoiceMode(
ListView.CHOICE_MODE_SINGLE);
}
@Override
public void onRefreshStarted(View view) {
new AsyncTask<Void, Void, Void>() {
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to {@link #execute}
* by the caller of this task.
* <p/>
* This method can call {@link #publishProgress} to publish updates
* on the UI thread.
*
* @param params The parameters of the task.
* @return A result, defined by the subclass of this task.
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
@Override
protected Void doInBackground(Void... params) {
if (newsFeedProvider.requestFeedRefresh()) {
listAdapter.updateShownNews();
}
return null;
}
/**
* <p>Runs on the UI thread after {@link #doInBackground}. The
* specified result is the value returned by {@link #doInBackground}.</p>
* <p/>
* <p>This method won't be invoked if the task was cancelled.</p>
*
* @param aVoid The result of the operation computed by {@link #doInBackground}.
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@Override
protected void onPostExecute(Void aVoid) {
mPullToRefreshLayout.setRefreshComplete();
}
/**
* <p>Applications should preferably override {@link #onCancelled(Object)}.
* This method is invoked by the default implementation of
* {@link #onCancelled(Object)}.</p>
* <p/>
* <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
* {@link #doInBackground(Object[])} has finished.</p>
*
* @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
@Override
protected void onCancelled() {
mPullToRefreshLayout.setRefreshComplete();
}
}.execute();
}
public interface NewsListFragmentListener {
public void onNewsArticleSelected(int index);
}
}
新闻阅读器活动:
public class NewsReaderActivity extends FragmentActivity implements
NewsListFragment.NewsListFragmentListener,
NavigationDrawerFragment.NavigationDrawerCallbacks {
private Boolean isDualPane = Boolean.FALSE;
private NewsListFragment NEWS_FRAGMENT;
private WebViewerFragment WEB_FRAGMENT;
private int lastSelectedNavDrawerItem = 0;
private NavigationDrawerFragment mNavigationDrawerFragment;
private CharSequence mTitle;
private void restoreActionBar() {
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
}
/**
* Called when an item in the navigation drawer is selected.
*
* @param position
*/
@Override
public void onNavigationDrawerItemSelected(int position) {
if (position == lastSelectedNavDrawerItem) {
//We don't want to perform a useless fragment reload
return;
}
else {
lastSelectedNavDrawerItem = position;
}
//TODO The rest of the stuff
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
getMenuInflater().inflate(R.menu.standard, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
startActivity(new Intent(this, SettingsPreferenceActivity.class));
break;
default: //Up button
return super.onOptionsItemSelected(item);
}
return true;
}
public void onSectionAttached(int number) {
int shiftedPos = number + 1;
mTitle = Utils.getString(this, "title_section" + shiftedPos, "");
if (mTitle.toString().isEmpty()) {
mTitle = getString(R.string.title_section1);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news);
FragmentManager fragmentManager = getFragmentManager();
mNavigationDrawerFragment = (NavigationDrawerFragment)
fragmentManager.findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
NEWS_FRAGMENT =
(NewsListFragment) getFragmentManager().findFragmentById(R.id.fragment_news);
WEB_FRAGMENT =
(WebViewerFragment) getFragmentManager().findFragmentById(R.id.fragment_web_viewer);
View webView = findViewById(R.id.fragment_web_viewer);
isDualPane = webView != null && webView.getVisibility() == View.VISIBLE;
restoreState(savedInstanceState);
}
private void restoreState(Bundle savedInstanceState) {
if (savedInstanceState != null) {
int index = savedInstanceState.getInt("index", 0);
NEWS_FRAGMENT.setSelection(index);
onNewsArticleSelected(index);
}
}
@Override
public void onNewsArticleSelected(int index) {
showUrlInWebViewerFragment(index);
}
private void showUrlInWebViewerFragment(int index) {
if (isDualPane) {
WEB_FRAGMENT.loadUrl(SQLiteBridge.getSingleton().getNews().get(index).getLink());
}
else {
Intent singleViewIntent = new Intent(this, WebViewerActivity.class);
singleViewIntent.putExtra("index", index);
startActivity(singleViewIntent);
}
}
}
值土地/layouts.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="activity_news" type="layout">@layout/news_double_pane</item>
<bool name="has_two_panes">true</bool>
</resources>
值/layouts.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="activity_news" type="layout">@layout/news_single_pane</item>
<bool name="has_two_panes">true</bool>
</resources>
news_double_pane.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"
tools:context="org.jorge.lolin1.activities.MainActivity">
<fragment
android:id="@+id/fragment_news"
android:name="org.jorge.lolin1.frags.NewsListFragment"
android:layout_width="@dimen/feed_item_length_percentage"
android:layout_height="match_parent"/>
<fragment
android:id="@+id/fragment_web_viewer"
android:name="org.jorge.lolin1.frags.WebViewerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/nothing_to_do_here"/>
<fragment
android:id="@+id/navigation_drawer"
android:name="org.jorge.lolin1.frags.NavigationDrawerFragment"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="left"/>
</android.support.v4.widget.DrawerLayout>
news_single_pane.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.jorge.lolin1.activities.MainActivity">
<fragment android:id="@+id/fragment_news"
android:name="org.jorge.lolin1.frags.NewsListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<fragment
android:id="@+id/navigation_drawer"
android:name="org.jorge.lolin1.frags.NavigationDrawerFragment"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="left"/>
</android.support.v4.widget.DrawerLayout>