【问题标题】:Switching between Landscape and Portrait mode using Fragments使用 Fragments 在横向和纵向模式之间切换
【发布时间】:2014-09-22 06:36:15
【问题描述】:

我有一个非常简单的应用程序,可以在横向模式和纵向模式之间切换。在纵向模式下,我有一个在列表中显示数据的片段,在横向模式下,我有另一个在网格中显示我的数据的片段。只是为了重新迭代有两个不同的片段,一个以纵向模式呈现数据的 ListFragment 和一个以横向模式显示数据的“GridFragment”。只要设备方向不变,各个片段就会正确呈现。然而,当设备从纵向翻转到横向或反之亦然时,该应用程序就会崩溃。

首先是我的错误日志。设备从纵向模式翻转到横向模式时的错误日志:

09-22 11:48:38.990:E/AndroidRuntime(29737):致命异常:主要 09-22 11:48:38.990: E/AndroidRuntime(29737): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.funapp.ssnd/com.funapp.ssnd.MainActivity}: java.lang.RuntimeException: 你的content 必须有一个 id 属性为 'android.R.id.list' 的 ListView 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3677) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.access$700(ActivityThread.java:149) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.os.Handler.dispatchMessage(Handler.java:99) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.os.Looper.loop(Looper.java:153) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.main(ActivityThread.java:4987) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 java.lang.reflect.Method.invokeNative(Native Method) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 java.lang.reflect.Method.invoke(Method.java:511) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584) 09-22 11:48:38.990: E/AndroidRuntime(29737): at dalvik.system.NativeStart.main(Native Method) 09-22 11:48:38.990: E/AndroidRuntime(29737): Caused by: java.lang.RuntimeException: 你的内容必须有一个 id 属性为 'android.R.id.list' 的 ListView 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.ListFragment.ensureList(ListFragment.java:344) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.ListFragment.onViewCreated(ListFragment.java:145) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:956) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1901) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:567) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.Activity.performStart(Activity.java:5030) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157) 09-22 11:48:38.990: E/AndroidRuntime(29737): ... 12 更多

以及设备从横向变为纵向时的错误日志:

09-22 11:52:20.906: E/AndroidRuntime(29943): 致命异常: main 09-22 11:52:20.906: E/AndroidRuntime(29943): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.funapp.ssnd/com.funapp.ssnd.MainActivity}: java.lang.NullPointerException 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3677) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.access$700(ActivityThread.java:149) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.os.Handler.dispatchMessage(Handler.java:99) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.os.Looper.loop(Looper.java:153) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.main(ActivityThread.java:4987) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 java.lang.reflect.Method.invokeNative(Native Method) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 java.lang.reflect.Method.invoke(Method.java:511) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584) 09-22 11:52:20.906: E/AndroidRuntime(29943): at dalvik.system.NativeStart.main(Native Method) 09-22 11:52:20.906: E/AndroidRuntime(29943): 引起: java.lang.NullPointerException 09-22 11:52:20.906: E/AndroidRuntime(29943): at com.funapp.ssnd.DetailsFragment.onActivityCreated(DetailsFragment.java:59) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1512) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:962) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1901) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:567) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.Activity.performStart(Activity.java:5030) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157) 09-22 11:52:20.906: E/AndroidRuntime(29943): ... 12 更多

包含 Fragments 的 Activity:

import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

     Configuration config = getResources().getConfiguration();

     if(config.orientation == Configuration.ORIENTATION_PORTRAIT){

         setContentView(R.layout.activity_main);
         FragmentManager manager = getSupportFragmentManager();
         FragmentTransaction transaction = manager.beginTransaction();
         MemberListFragment fragment1 = new MemberListFragment();
         transaction.add(R.id.fragment_container,fragment1);
         transaction.commit();
     }

     if(config.orientation == Configuration.ORIENTATION_LANDSCAPE){

         setContentView(R.layout.activity_main);
         FragmentManager manager = getSupportFragmentManager();
         FragmentTransaction transaction = manager.beginTransaction();
         DetailsFragment fragment2 = new DetailsFragment();
         transaction.add(R.id.fragment_container,fragment2);
         transaction.commit();
     }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

还有布局文件。对于纵向模式:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView android:id="@id/android:list"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:layout_weight="1"
           android:drawSelectorOnTop="false"/>



</LinearLayout>

对于横向模式:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"

/>

还有碎片。对于纵向模式:

import java.util.ArrayList;
import java.util.List;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MemberListFragment extends ListFragment {

String[] membersList;
Integer[] imageList;
ListView listView;
List<RowItem> rowItems;

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

    return inflater.inflate(R.layout.fragment_layout, container,false);

}


@Override
public void onActivityCreated(Bundle savedInstanceState){

    super.onActivityCreated(savedInstanceState);


    rowItems = new ArrayList<RowItem>();

    membersList = (getResources().getStringArray(R.array.snsd_members));
    imageList = new Integer[membersList.length];

    for(int i=0; i<membersList.length; i++){

        imageList[i] = R.drawable.home;
    }

    for(int i=0; i<membersList.length; i++){

        RowItem item = new RowItem(imageList[i], membersList[i]);
        rowItems.add(item);
    }

    listView = (ListView) getListView();
    SNSDAdapter adapter = new SNSDAdapter(getActivity().getApplicationContext(),
            R.layout.list_element, rowItems);
    listView.setAdapter(adapter);

}



}

和横向模式:

import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;

public class DetailsFragment extends Fragment {

String[] membersList;
Integer[] imageList;
GridView gridView;
List<RowItem> rowItems;

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

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

    gridView = (GridView)view.findViewById(R.id.grid_view);

    return view;

}  

@Override
public void onActivityCreated(Bundle savedInstanceState){

    super.onActivityCreated(savedInstanceState);


    rowItems = new ArrayList<RowItem>();

    membersList = (getResources().getStringArray(R.array.snsd_members));
    imageList = new Integer[membersList.length];

    for(int i=0; i<membersList.length; i++){

        imageList[i] = R.drawable.home;
    }

    for(int i=0; i<membersList.length; i++){

        RowItem item = new RowItem(imageList[i], membersList[i]);
        rowItems.add(item);
    }

    Log.v("ROW ITEMS",rowItems.toString());
    GridAdapter adapter = new GridAdapter(getActivity().getApplicationContext(),rowItems);
    gridView.setAdapter(adapter);

}




}

我花了很多时间试图解决这个问题,但没有找到解决方案。这可能是因为当屏幕旋转时我的 Fragments 并没有真正“销毁”,从而阻止了新的 Fragment 取代它的位置?任何解决方案或某些方向将不胜感激。

【问题讨论】:

  • 异常来自您的片段代码。您能否也显示此代码(相关部分)?
  • @Szymon 我也添加了片段代码。
  • 您的清单中的活动声明中是否有类似“android:configChanges="orientation"" 的行?
  • @labreu 不,我的清单中没有该设置。
  • 如果知道是否有帮助,如果我在横向模式下使用列表视图并将一个片段替换为另一个片段,则方向更改是无缝的并且应用程序不会崩溃。然而,在这种情况下,从列表视图切换到网格视图(反之亦然)不会给我预期的结果。同样在 MainActivity 中,我不替换任何片段,而是在每次设备方向更改时添加它们。这是解决这个问题的正确方法吗?

标签: android android-fragments android-orientation


【解决方案1】:

检查您在 XML 文件中的 ListView id... 应该是android:id="@android:id/list"

【讨论】:

  • 当应用程序以纵向模式呈现时,它会按预期显示一个 ListView。当设备方向从纵向变为横向时,它看起来好像我的活动仍然需要一个列表视图,而实际上应该呈现一个网格视图。这是否意味着每次设备方向更改时都会重新创建我的“列表视图”片段?同样适用于从横向模式到纵向模式的更改。了解每个方向更改的错误日志可能会有所帮助。
  • 可能在横向模式下 Activity 无法找到 ListView..所以你只需在横向模式下禁用列表视图..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
相关资源
最近更新 更多