petrfaitl
petrfaitl

Reputation: 13

findViewByID(android.R.id.list) returns null with ListFragment

Let me first state that I'm aware that it is frowned upon enclosing ListView inside a ScrollView. However, I had the layout working perfectly well by using Activity class. I've now tried to do the same by using Fragments and just cannot get there.

The interaction between fragments is working fine and the listView populates from the data entry screen. However the ListView appears collapsed to just a few lines. To compensate I'm trying to re-size the ListView to have the height of the arrayList plus dividers. To achieve that I need to get a reference to the list View, which I fail to do.

The problem seems to lie in trying to get a reference to a ListView, either by (ListView)findViewById(android.R.id.list) which returns null or by MySkeletonFragmentActivity.this.resultsFragment.getListView(), which returns view not yet created error. (look for resultsListAlt).

Main Activity This manages the interaction between fragments

public class MySkeletonFragmentActivity extends Activity implements DataEntryFragment.OnDataSubmitListener
{
private ArrayAdapter<String> aa;
private ArrayList<String> results;
private String distance;
private ResultsFragment resultsFragment;
private DataEntryFragment dataEntryFragment;

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

    FragmentManager fragmentManager = getFragmentManager();
    resultsFragment = (ResultsFragment)fragmentManager.findFragmentById(R.id.results_container);
    dataEntryFragment = (DataEntryFragment)fragmentManager.findFragmentById(R.layout.data_entry_fragment);

    if(resultsFragment == null || dataEntryFragment == null)
    {
        FragmentTransaction fT = fragmentManager.beginTransaction();
        fT.replace(R.id.data_entry_fragment_container, new DataEntryFragment());
        resultsFragment = new ResultsFragment();
        fT.replace(R.id.results_container, resultsFragment );
        fT.addToBackStack(null);
        fT.commit();
        results = new ArrayList<String>();
        aa = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,results);
        resultsFragment.setListAdapter(aa);
        ListView resultsList = (ListView)findViewById(android.R.id.list);
        ListView resultsListAlt = MySkeletonFragmentActivity.this.resultsFragment.getListView(); // view not yet created error

//set height of listView
        int height = 0;
        for (int i = 0; i<results.size();i++)
        {
            View arrayItem = aa.getView(i, null, resultsList);
            arrayItem.measure(0,0);
            height += arrayItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = resultsList.getLayoutParams(); // resultsList == null
        params.height = height + (resultsList.getDividerHeight() * (results.size() -1));
        resultsList.setLayoutParams(params);
        resultsList.requestLayout();

    }

Results fragment XML

<?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"
android:id="@+id/results_fragment_layout"
>
<TextView 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/results"
    android:textSize="@dimen/header_text_size"
    android:paddingBottom="@dimen/activity_vertical_margin"/>
<ListView 
    android:id="@android:id/list"
    android:tag="results_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</ListView>
</LinearLayout>

Results Fragment

public class ResultsFragment extends ListFragment
{

@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState  )
{
    super.onCreateView(inflater, container, savedInstanceState);
    View resultsLayout = inflater.inflate(R.layout.results_fragment,container, false);


    return resultsLayout;
}

}

Questions: 1) Why am I not getting reference to the List view and getting null on resultsList? 2) Where to call getView(), as in resultsListAlt, to get the reference and to be able to affect the size of the listView? I tried in onResume(), but the size of the listView remained unchanged. 3) Is there altogether better way of creating the same layout, where you can scroll from the data entry to the results?

I used fragments to be able to present different layout for landscape and/or larger devices.

For illustration of the app, I'm including a screenshot of my webView wrapper app. Where in the top section, you have a data entry (DataEntryFragment) and in the bottom half the list of results (ResultFragment).

enter image description here

Upvotes: 0

Views: 1385

Answers (1)

CommonsWare
CommonsWare

Reputation: 1006604

commit() is asynchronous. Your ListView will not be created until long after you call commit(). Move your populate-the-fragment logic into the fragment itself, in its onCreateView() method, as there you not only know the ListView is created, but you can retrieve it by calling findViewById() on resultsLayout.

Upvotes: 3

Related Questions