Tablet Screen Orientation Change - No View found f

2019-02-12 17:25发布

I have looked at questions related to my problem on SO but couldn't figure out what the problem is. Bear with me if this is a repost.

Here is what i am looking for:

Phone Portrait Mode

Phone Landscape Mode

The layout changes for phone are working fine as it involves the same views inside the fragment. The problem is when i try get the below layout in tablets.

Tablet Portrait Mode

Tablet Landscape Mode

My Layout Structure

activity_main.xml in portrait mode:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar_with_spinner" />

        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
        </FrameLayout>
    </LinearLayout>

    <ListView
        android:id="@+id/listview_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white"
        android:choiceMode="singleChoice"
        android:divider="@null"
        android:dividerHeight="0dp" />

</android.support.v4.widget.DrawerLayout>

activity_main.xml in landscape mode:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar_with_spinner" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:baselineAligned="false"
            android:orientation="horizontal" >

            <FrameLayout
                android:id="@+id/fragment_container"
                android:layout_width="0dip"
                android:layout_height="match_parent"
                android:layout_weight="0.40" />

            <FrameLayout
                android:id="@+id/detail_fragment_container"
                android:layout_width="0dip"
                android:layout_height="match_parent"
                android:layout_weight="0.60" />
        </LinearLayout>
    </LinearLayout>

    <ListView
        android:id="@+id/listview_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white"
        android:choiceMode="singleChoice"
        android:divider="@null"
        android:dividerHeight="0dp" />

</android.support.v4.widget.DrawerLayout>

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipeRefreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:orientation="vertical"
    android:padding="4dp" >

    <GridView
        android:id="@+id/gridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:horizontalSpacing="0dp"
        android:numColumns="3"
        android:stretchMode="columnWidth"
        android:verticalSpacing="0dp" >
    </GridView>

    <WebView
        android:id="@+id/webview_fragment_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

</android.support.v4.widget.SwipeRefreshLayout>

MainActivity - onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (Const.DEBUGGING_INT)
        Log.d(Const.DEBUG, "Activity - onCreate");

    prefs = PreferenceManager.getDefaultSharedPreferences(this);

    if (Const.DEBUGGING)
        Log.d(Const.DEBUG, "Index = " + index);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    spinner = (Spinner) toolbar.findViewById(R.id.spinner);
    mDrawerList = (ListView) findViewById(R.id.listview_drawer);

    setUpHeaderAndFooter();

    setSupportActionBar(toolbar);
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setTitle("");

    setUpToolBar();
    setUpSpinner();
    setUpNavigationDrawer();

    if ((findViewById(R.id.fragment_container) != null)
            && (findViewById(R.id.detail_fragment_container) != null)) {
        mTwoPane = true;
    } else {
        mTwoPane = false;
    }

    setFragment(prefs.getInt(Const.Prefs.MAININDEX, 0), 0);

}

setFragment Method in MainActivity:

private void setFragment(int mainIndex, int subIndex) {

    if (Const.DEBUGGING_INT) {
        Log.d(Const.DEBUG, "Activity - setFragment");
        Log.d(Const.DEBUG, "Position = " + mainIndex);
        Log.d(Const.DEBUG, "TwoPane? " + mTwoPane);
    }

    incrementClickCount(mainIndex);

    mMainFragment = new MainFragment();
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.fragment_container, mMainFragment).commit();

    Bundle bundle = new Bundle();
    bundle.putInt(Const.BundleParameters.MAININDEX, mainIndex);
    bundle.putInt(Const.BundleParameters.SUBINDEX, subIndex);
    bundle.putBoolean(Const.BundleParameters.TWOPANE, mTwoPane);
    bundle.putInt(Const.BundleParameters.CURRENTPOSITION, 0);
    mMainFragment.setParameters(bundle);

    mDrawerList.setItemChecked(mainIndex, true);
    mDrawerLayout.closeDrawer(mDrawerList);

    if (mTwoPane) {

        mDetailFragment = new DetailFragment();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.detail_fragment_container, mDetailFragment)
                .commit();

        if (Const.DEBUGGING)
            Log.d(Const.DEBUG,
                    "URL = " + prefs.getString(Const.Prefs.CURRENT_URL, ""));

        Bundle b = new Bundle();
        b.putString("url", prefs.getString(Const.Prefs.CURRENT_URL, ""));
        mDetailFragment.setParameters(b);
    }

}

MainFragment - onCreateView():

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    Log.d(Const.DEBUG, "Fragment - onCreateView");

    View view = inflater.inflate(R.layout.fragment_main, container, false);

    mSwipeRefreshLayout = (SwipeRefreshLayout) view
            .findViewById(R.id.swipeRefreshLayout);
    mSwipeRefreshLayout.setOnRefreshListener(this);
    mSwipeRefreshLayout.setColorSchemeResources(R.color.blue,
            R.color.green, R.color.pink, R.color.yellow);

    // if (!mSwipeRefreshLayout.isRefreshing())
    mSwipeRefreshLayout.setRefreshing(true);

    prefs = PreferenceManager.getDefaultSharedPreferences(activity);

    mDbAdapter = DatabaseHelper.get(getActivity().getApplicationContext())
            .getDbAdapter();

    gridview = (GridView) view.findViewById(R.id.gridview);
    webview = (WebView) view.findViewById(R.id.webview_fragment_main);
    webview.setWebViewClient(new MyWebViewClient());
    webview.setWebChromeClient(new WebChromeClient() {
        @Override
        public boolean onJsAlert(WebView view, String url, String message,
                JsResult result) {
            return super.onJsAlert(view, url, message, result);
        }
    });

    WebSettings settings = webview.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
    webview.setVerticalScrollBarEnabled(false);
    webview.setHorizontalScrollBarEnabled(false);

    setTableDetails();

    isTableEmpty = mDbAdapter.isTableEmpty(mTableName);
    if (isTableEmpty) {
        getDataFromServer(true);
    } else {
        checkRefreshTimeAndGetData();
    }

    return view;
}

DetailFragment - onCreateView():

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    if (Const.DEBUGGING) {
        Log.d(Const.DEBUG, "***** DetailFragment - onCreateView *****");
        Log.d(Const.DEBUG, "URL = " + url);
    }

    View view = inflater
            .inflate(R.layout.fragment_detail, container, false);

    prefs = PreferenceManager.getDefaultSharedPreferences(activity);
    pd = (ProgressBar) view.findViewById(R.id.progressBar);

    webview = (WebView) view.findViewById(R.id.webview_fragment_detail);
    webview.setWebViewClient(new MyWebViewClient());
    webview.setWebChromeClient(new WebChromeClient() {
        @Override
        public boolean onJsAlert(WebView view, String url, String message,
                JsResult result) {
            return super.onJsAlert(view, url, message, result);
        }
    });

    pd.setVisibility(View.VISIBLE);
    webview.setVisibility(View.GONE);

    WebSettings settings = webview.getSettings();
    settings.setJavaScriptEnabled(true);
    webview.setVerticalScrollBarEnabled(false);
    webview.setHorizontalScrollBarEnabled(false);
    webview.loadUrl(url);
    // webview.loadDataWithBaseURL(url, null, "text/html", "utf-8", null);

    return view;
}

Logcat:

11-16 23:15:05.234: E/FragmentManager(26609): No view found for id 0x7f0a0052 (com.xx.xxx:id/detail_fragment_container) for fragment DetailFragment{42476ab8 #1 id=0x7f0a0052}

I understand that it's looking for detail_fragment_container, that i don't have in portrait mode. How do i fix this? Let me know if you need the code as well. Will be glad to post..

3条回答
Bombasti
2楼-- · 2019-02-12 18:01

Change the code,

if ((findViewById(R.id.fragment_container) != null)
            && (findViewById(R.id.detail_fragment_container) != null)) {
        mTwoPane = true;
    } else {
        mTwoPane = false;
    }

by

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
    //Do some stuff
mTwoPane = true;
} else{
 mTwoPane = false;
}

hope it will help you

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-02-12 18:17

The only way I can think of you getting that error is that your old layout is used. That could be because super.onCreate(savedInstanceState);

Instead try ignoring the saved state:

super.onCreate(null);

Edit:

Response to @matiash comment:

Since OP didn't provide code to re-create the problem, it's hard to test other (if any) solutions.

However I do agree that resetting the savedInstanceState is kind of an overkill. Therefore I think OP should try it himself and see to it that he saves as many views as possible.

The first thing that comes to mind is preventing the problematic view from being saved:

<FrameLayout
    android:id="@+id/detail_fragment_container"
    android:layout_width="0dip"
    android:layout_height="match_parent"
    android:layout_weight="0.60"
    android:saveEnabled="false"/>
查看更多
Deceive 欺骗
4楼-- · 2019-02-12 18:20

The FragmentManager will try to recreate all the fragments when rotated, but in portrait mode you don't have the DetailFragment layout anymore, so you should remove the fragment to prevent it from being attached.

EDIT: Perhaps the cleanest way to detect your orientation change is to use the OrientationEventListener. You can refer to this post and this for some example. You should remove the fragment inside the method onOrientationChanged (int orientation) which you should override.

查看更多
登录 后发表回答