-1

I'm having two issues with my Android application. I'll start with the relevant code, which I'm 99% certain is locked within my MainActivity class:

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);
}
}

(Note that I'm not concerned with the code within the onItemSelected at the moment; I'll deal with that later, when I actually have working code.)

So my first problem is with this line:

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

What I'm hoping to attain here is the ListView found in the current display (in portrait or landscape mode, the list view will be displayed). I also attempted another method in the commented out line above that, but it also failed. The error here is a NullPointerException.

My second issue is that whenever I go to portrait mode from landscape mode, the application crashes. I can go from portrait to landscape, and boot in either mode, but going back to portrait kills the application. I've made the proper checks for orientation in onCreate so I'm not sure of where I'm going wrong. The error here states that there's no TextView to find in the current view- but that should only be called when I'm in landscape mode, right?

Anyways, any help would be greatly appreciated!

Here are my layouts:

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 (portrait)

<?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>
SFX
  • 169
  • 11

2 Answers2

0

First, try moving the code where you get the list view to the fragment.

Also, in

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

you overwrite the text even if there was no TEXT fragment before, in case there's a savedInstance

Finally, you have duplicate ids:

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

and

<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
  • Ah. In my mind what I thought was happening was that the FrameLayout was trying to find the WebView with the id "text". Thanks! So are you suggesting I remove the text set? – SFX Mar 19 '14 at 02:42
  • Change one of the IDs to something different from "text". And regarding text variable, maybe you created the fragment then overwrote to null. At least test if findFragmentByTag != null before overwriting – Douglas Drumond Kayama Mar 19 '14 at 03:07
0

Firstly, I don't see your ListView set to an Adapter in your activity. Here is just a simple example, where customtextview is a simple TextView and items a string array:

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

Then, you have two id with "text" (R.layout.text_view and FrameLayout in R.layout.main landscape). If you use both in one of your Fragment, this will crash. Change one of them..

And, because you have the FrameLayout "text" only in landscape mode, you can do your onCreate method as below (check if this FrameLayout is present or not):

@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
    */
}

Then, in your RSS Fragment, set your 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;
}

To save a fragment state on a activity, you can use setRetainInstance(true). There is a great post on it, and a tutorial. For more information about what happens with fragment and orientation changed, you can read this answer.

Let me know if this is helpful.


I searched a bit on the web, and I found these tutorials which might help you a lot:

  1. great: Create Android Dynamic view with Fragments
  2. great: User Interface Design: Working With Fragments
  3. not bad: Fragment example tutorial using WebView

All works with WebView and they mostly use findFragmentById and not tag. Maybe it's the clue..
But you can add directly on the xml the appropriate fragments, as:

- 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  

And on your FragmentActivity, you host your list and check the orientation, like the following:

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
}

This should work..
I hope these added informations will help you to achieve that.

Community
  • 1
  • 1
Blo
  • 11,903
  • 5
  • 45
  • 99
  • This is very helpful, thank you! However, I'm attempting your approach, and I still crash on going from landscape to portrait mode. It's now telling me "No view found for id 0x7f050003 (com.simplerssreader:id/textLandscape) for fragment TextFragment". Any insight? – SFX Mar 19 '14 at 03:41
  • Try destroying the fragment that you create only if landscape. It's possible that the systems try to restore its state and therefore has an extra fragment and he doesn't know where to put it. – k3v1n4ud3 Mar 19 '14 at 03:53
  • @SFX I updated my answer according to k3v1n4ud3's answer about setting your list inside your fragment rather than in your activity. I also added urls for tutorials displaying webview regarding to the orientation, and a solution to display your list inside your fragmentactivity. HTH. – Blo Mar 19 '14 at 14:59