How do I implement ListViews with Viewpager?

2019-05-11 16:04发布

问题:

I'm a noob to android develop and i am trying to show a listview within a viewpager. However, when i try to run the application it crashes during onCreate due to a nullpointerexception. This line is causing the exception:

listView.setAdapter(new UserItemAdapter(MyPagerActivity.this, R.layout.listitem, tweets));

i used the tutorial here so i don't understand why i am having this issue. Am I instantiating the listview properly? Any help is greatly appreciated.

public class MyPagerActivity extends Activity {

///////////////////////
ArrayList<Tweet> tweets;
ProgressDialog dialog;
Handler handler; 
ImageLoader tango;


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

    MyPagerAdapter adapter = new MyPagerAdapter();
    ViewPager myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
    myPager.setAdapter(adapter);
    myPager.setCurrentItem(0);

    //////////////////////
    tango = new ImageLoader(MyPagerActivity.this); 
    tweets = new ArrayList<Tweet>();

    try {           
        JSONObject jArray = JSONfunctions.getJSONfromURL("http://search.twitter.com/search.json?q=gold%20silver%20news&rpp=15");
        JSONArray parsedTwitter = jArray.getJSONArray("results");       
        if(parsedTwitter.equals("") ){
            Toast.makeText(MyPagerActivity.this, "No twitter news", Toast.LENGTH_LONG).show();
        }else{
            for (int i = 0; i < parsedTwitter.length(); i++) {
            JSONObject parsedspecific = parsedTwitter.getJSONObject(i);             
        if (i == 0){                
            String from_user = parsedspecific.getString("from_user");
            String text = parsedspecific.getString("text"); 
            String profile_image_url = parsedspecific.getString("profile_image_url");  
            Tweet tweet0 = new Tweet(from_user, text, profile_image_url );
            tweets.add(tweet0);                 
            }

              }//<--for close
            }//<--else close

    } catch (Exception e) {
        Log.e("log_tag", "Error parsing data "+ e.toString());
    }

    ListView listView = (ListView) findViewById(R.id.ListViewId);  
    listView.setAdapter(new UserItemAdapter(MyPagerActivity.this, R.layout.listitem, tweets));

}



private class MyPagerAdapter extends PagerAdapter {

    public int getCount() {
        return 5;
    }

    public Object instantiateItem(View collection, int position) {

        LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);


        int resId = 0;
        switch (position) {
        case 0:
            resId = R.layout.news;
            break;
        case 1:
            resId = R.layout.coinshows;
            break;
        case 2:
            resId = R.layout.twitterlist;
            break;
        case 3:
            resId = R.layout.videos;
            break;
    //  case 4:
    //      resId = R.layout.farright;
    //      break;
        }

        View view = inflater.inflate(resId, null);

        ((ViewPager) collection).addView(view, 0);

        return view;
    }



}

XML causing null:

<?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/ListViewId"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

MyPagerMain XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/tab2"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v4.view.ViewPager
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:id="@+id/myfivepanelpager"
android:background="#234567"/>
</LinearLayout>

EDIT based on Dennis Drew's answer (still causes nullpointer)

private class MyPagerAdapter extends PagerAdapter {

    public int getCount() {
        return 5;
    }

    public Object instantiateItem(View collection, int position) {

        LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);


        int resId = 0;
        switch (position) {
        case 0:
            resId = R.layout.news;
            View view0 = inflater.inflate(resId, null);
            WebView newsfeed = (WebView) findViewById(R.id.webViewnews);
            ((ViewPager) collection).addView(view0, 0);
            return view0;

        case 1:
            resId = R.layout.coinshows;
            View view1 = inflater.inflate(resId, null);
            WebView coinshows = (WebView) findViewById(R.id.webViewcoinshows);
            ((ViewPager) collection).addView(view1, 0);
            return view1;

        case 2:
            resId = R.layout.twitterlist;
            View view2 = inflater.inflate(resId, null);
            LinearLayout layout=(LinearLayout)view2.findViewById(R.id.LLtwitter);
            ListView listView = (ListView) findViewById(R.id.ListViewId);  
            listView.setAdapter(new UserItemAdapter(MyPagerActivity.this, R.layout.listitem, tweets));
            ((ViewPager) collection).addView(view2, 0);
            return view2;
            //break;
        case 3:
            resId = R.layout.videos;
            View view3 = inflater.inflate(resId, null);             
            WebView youtube = (WebView) findViewById(R.id.webViewyoutube);
            ((ViewPager) collection).addView(view3, 0);
            return view3;


        }
        return resId;


    }

回答1:

What's happening is your findViewById is returning null on the ListView because it is inside the ViewPager. You must initialize your ListView in your PagerAdapter's instantiateItem after the view for the current item has been inflated. Check my answer to a similar issue here: ViewPager findViewById

EDIT: Updating to clarify with example code

public Object instantiateItem(View collection, int position) {

    LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);


    int resId = 0;
    switch (position) {
    case 0:
        resId = R.layout.news;
        View view0 = inflater.inflate(resId, null);
        WebView newsfeed = (WebView) findViewById(R.id.webViewnews);
        ((ViewPager) collection).addView(view0, 0);
        return view0;

    case 1:
        resId = R.layout.coinshows;
        View view1 = inflater.inflate(resId, null);
        WebView coinshows = (WebView) findViewById(R.id.webViewcoinshows);
        ((ViewPager) collection).addView(view1, 0);
        return view1;

    case 2:
        resId = R.layout.twitterlist;
        View view2 = inflater.inflate(resId, null);
        LinearLayout layout=(LinearLayout)view2.findViewById(R.id.LLtwitter);

        //Pay close attention to this modification
        //Rather than this --> ListView listView = (ListView) findViewById(R.id.ListViewId);  

        //Do this
        ListView listView = (ListView)view2.findViewById(R.id.ListViewId);
        listView.setAdapter(new UserItemAdapter(MyPagerActivity.this, R.layout.listitem, tweets));
        ((ViewPager) collection).addView(view2, 0);
        return view2;
        //break;
    case 3:
        resId = R.layout.videos;
        View view3 = inflater.inflate(resId, null);             
        WebView youtube = (WebView) findViewById(R.id.webViewyoutube);
        ((ViewPager) collection).addView(view3, 0);
        return view3;


    }
    return resId;


}

Think of your instantiateItem method almost like a sub-onCreate, in the sense that instead of just calling findViewById, you must call findViewById on the view that's inflated in each individual pager item to do findViewById (view.findViewById). Hope this helps.