Android App:MainActivity无法在Landscape-> Portrait Mode上查找ListView / Crashes

时间:2014-03-19 01:34:27

标签: android listview crash landscape portrait

我的Android应用程序存在两个问题。我将从相关代码开始,我肯定99%已锁定在我的MainActivity类中:

package com.simplerssreader;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

public class MainActivity extends FragmentActivity {

private ListView list;
private TextFragment text;
private RssFragment rss;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {

        // Initializing AddNote fragment
        if (getFragmentManager().findFragmentByTag("RSS") == null)
        {
            rss = new RssFragment();
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, rss, "RSS").commit();
        }

    }

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        if (getFragmentManager().findFragmentByTag("RSS") == null)
        {
            rss = new RssFragment();
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, rss, "RSS").commit();
        }
        if (getFragmentManager().findFragmentByTag("TEXT") == null)
        {
            text = new TextFragment();
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.text, text, "TEXT").commit();
        }
    }

    //View view = getLayoutInflater().inflate(R.layout.fragment_layout, null);
    list = (ListView) this.findViewById(R.id.listView);
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) 
        {
            System.out.println("YES!");
            /*RssAdapter adapter = (RssAdapter) parent.getAdapter();
            RssItem item = (RssItem) adapter.getItem(position);
            TextFragment fragment = new TextFragment();
            fragment.setLink(item.getLink());
            FragmentManager fragMgr = getSupportFragmentManager();
            FragmentTransaction xact = fragMgr.beginTransaction();
            xact.replace(R.id.text, fragment, "TEXT");*/
        }
    });

    if (savedInstanceState != null) {
        text = (TextFragment) getSupportFragmentManager().findFragmentByTag("TEXT");
        rss = (RssFragment) getSupportFragmentManager().findFragmentByTag("RSS");
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean("fragment_added", true);
}
}

(请注意,我现在并不关心onItemSelected中的代码;当我实际使用代码时,我将在稍后处理它。)

所以我的第一个问题是这一行:

list = (ListView) this.findViewById(R.id.listView);

我希望在这里获得的是在当前显示中找到的ListView(在纵向或横向模式下,将显示列表视图)。我也在上面注释掉的行中尝试了另一种方法,但它也失败了。这里的错误是NullPointerException。

我的第二个问题是每当我从横向模式进入纵向模式时,应用程序崩溃。我可以从纵向到横向,并以任一模式启动,但回到肖像会杀死应用程序。我已经对onCreate的方向进行了适当的检查,所以我不确定我哪里出错了。这里的错误表明在当前视图中没有要查找的TextView,但只有当我在横向模式下才能调用它,对吗?

无论如何,非常感谢任何帮助!

以下是我的布局:

fragment_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/listView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
</ListView>

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleLarge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true" />

</RelativeLayout>

main.xml(肖像)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:id="@+id/fragment_container"
android:layout_height="fill_parent" 

/>

text_view.xml

<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>

main.xml(landscape)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_height="match_parent" 
android:baselineAligned="false">

  <FrameLayout android:id="@+id/fragment_container" android:layout_weight="1"
        android:layout_width="0px" android:layout_height="match_parent"
        android:background="?android:attr/detailsElementBackground" />

  <FrameLayout android:id="@+id/text" android:layout_weight="2"
        android:layout_width="0px" android:layout_height="match_parent"
        android:background="?android:attr/detailsElementBackground" />

 </LinearLayout>

2 个答案:

答案 0 :(得分:0)

首先,尝试将获取列表视图的代码移动到片段。

另外,

if (savedInstanceState != null) {
    text = (TextFragment) getSupportFragmentManager().findFragmentByTag("TEXT");
    rss = (RssFragment) getSupportFragmentManager().findFragmentByTag("RSS");
}
如果以前没有TEXT片段,

你会覆盖text,以防savedInstance

最后,您有重复的ID:

<FrameLayout android:id="@+id/text" android:layout_weight="2"
    android:layout_width="0px" android:layout_height="match_parent"
    android:background="?android:attr/detailsElementBackground" />

<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

答案 1 :(得分:0)

首先,我在您的活动中看不到您的ListView设置为Adapter。这只是一个简单的示例,其中customtextview是一个简单的TextViewitems一个字符串数组:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.customtextview, items);
listView.setAdapter(adapter);

然后,您有两个带有“text”(R.layout.text_viewR.layout.main风景中的FrameLayout)的ID。如果你在其中一个片段中使用它们,这将会崩溃。改变其中一个..

并且,因为您只在横向模式下拥有FrameLayout“文本”,所以您可以按照以下执行onCreate方法(检查此FrameLayout是否存在)

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // in both layout, you add this Fragment in the same FrameLayout
    // check the savedInstanceState, if isn't null = orientation has changed
    if (savedInstanceState == null)
        rss = new RssFragment();
        getSupportFragmentManager().beginTransaction()
            .add(R.id.fragment_container, rss, "RSS").commit();
    } else {
        rss = (RssFragment) getSupportFragmentManager().findFragmentByTag("RSS");
    }

    /*
    ** check if FrameLayout text is null (true = landscape)
    */
    if(findViewById(R.id.text) != null) {
        // check the savedInstanceState
        if (savedInstanceState == null) {
            text = new TextFragment();
            getSupportFragmentManager().beginTransaction()
                .add(R.id.text, text, "TEXT").commit();
        } else {
            text = (TextFragment) getSupportFragmentManager().findFragmentByTag("TEXT");
        }

    }
    /*
    ** else the id isn't exist (false = portrait) // do nothing
    */
}

然后,在RSS Fragment中,设置ListView

private ListView list;
String[] items = new String[] {
    "One",
    "Two",
    "Three",
    "And so on.."
};

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_layout, container, false);
    list = (ListView) v.findViewById(R.id.listView);
    ArrayAdapter<String> adapt = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, items);
    list.setAdapter(adapt);
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
            System.out.println("YES!");
            /* some stuff */
        }
    });
    return v;
}

要在活动中保存片段状态,您可以使用setRetainInstance(true)。它上面有一个great post和一个tutorial。有关片段和方向发生变化的更多信息,请阅读this answer

如果这有用,请告诉我。


我在网上搜索了一下,我发现这些教程可能对你有很大帮助

  1. 很棒:Create Android Dynamic view with Fragments
  2. 很棒:User Interface Design: Working With Fragments
  3. 不错:Fragment example tutorial using WebView
  4. 所有内容均适用于WebView,并且主要使用findFragmentById而非tag。也许这是线索..
    但是你可以直接在xml上添加适当的片段,如:

    - Portrait Mode :  
        o layout 1 : listview (ex fragment RSS)
        o layout 2 : fragment WebView
    - Landscape Mode : 
        o layout 1 : 
              LinearLayout (id container) : listview (ex fragment RSS) + framelayout  
    

    在您的FragmentActivity上,您托管列表并检查方向,如下所示:

    ListView list = (ListView) findViewById(...);
    list.setAdapter(...);
    LinearLayout container = (LinearLayout) findViewById(R.id.container);
    if(container != null) {
        // your framelayout is present so set your fragment WebView
        // inside it with a fragment transaction and also
        // use the item clicked to send info to this fragment
    } else {
        // call a new activity on item clicked to display the WebView
    }
    

    这应该有效。
    我希望这些添加的信息可以帮助您实现这一目标。