ViewPager和PagerAdapter

时间:2014-05-26 14:58:49

标签: android android-fragments android-pageradapter

我是Android新手,正在尝试使用自定义PagerAdapters和FragmentStatePagerAdapters在主 - 详细信息流中显示ViewPagers的示例应用程序。我的应用程序有一个由SQLiteDatabase管理的虚拟项目列表,其中包含标题String,描述StringBoolean状态和图像列表(I计划从String网址下载实现它们,但目前我只是尝试使用单个图像资源)。我在详细信息视图中遇到两个问题。

我的目的是使用ViewPagerFragmentStatePagerAdapter来显示详情视图,其中包含ViewPager个自定义PagerAdapter,用于显示图片列表,TextView表示标题和说明,ToggleButton表示类似状态,删除按钮表示从列表中删除项目。

的问题:

  1. 带有自定义PagerAdapter的ViewPager不显示图像。它占据了预期的空间,并且在其上执行的滑动也表现得如预期的那样。只有图像不可见。
  2. [已解决]使用删除按钮,我可以从数据库中删除该项目,并相应地更新主视图,但我无法更新详细信息视图,并且应用程序崩溃。
  3. 这是我的代码:

    调用ItemDetailActivity.java的代码

    @Override
    public void onClick(View v) {
        Intent detailIntent = new Intent(getContext(), ItemDetailActivity.class);
        detailIntent.putExtra(ItemDetailFragment.ARG_LIST_POSITION, holder.position);
        getContext().startActivity(detailIntent);
    }
    

    ItemDetailActivity.java

    public class ItemDetailActivity extends FragmentActivity {
    
        static ItemDetailPagerAdapter idpa;
    
        static ViewPager detailPager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_item_detail);
    
            idpa = new ItemDetailPagerAdapter(getSupportFragmentManager());
    
            // Show the Up button in the action bar.
            getActionBar().setDisplayHomeAsUpEnabled(true);
    
            detailPager = (ViewPager) findViewById(R.id.item_detail_container);
            detailPager.setAdapter(idpa);
            detailPager.setCurrentItem(getIntent().getIntExtra(ItemDetailFragment.ARG_LIST_POSITION, 0));
        }
    }
    

    activity_item_detail.xml

    <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/item_detail_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.trial.piclist.ItemDetailActivity"
        tools:ignore="MergeRootFrame" />
    

    ItemDetailFragment.java

    public class ItemDetailFragment extends Fragment {
        public static final String ARG_ITEM_ID = "item_id";
        public static final String ARG_LIST_POSITION = "list_index";
        public static final String ARG_TWO_PANE = "is_two_pane";
        int position = -1;
        long id = -1;
        boolean twoPane = false;
        ViewPager pager;
        private PicItem mItem;
    
        public ItemDetailFragment() {
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            twoPane = getArguments().getBoolean(ARG_TWO_PANE, false);
            position = getArguments().getInt(ARG_LIST_POSITION, -1);
            id = getArguments().getLong(ARG_ITEM_ID, -1);
            if (id == -1)
                id = ItemListFragment.getIdByPosition(position);
            setmItem(id);
        }
    
        public void setmItem(long id) {
            if (id >= 0) {
                try {
                    ItemListActivity.lds.open();
                    mItem = ItemListActivity.lds.getById(id);
                    ItemListActivity.lds.close();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                if (mItem != null) {
                    List<String> pics = new ArrayList<String>();
                    pics.add("1");
                    pics.add("2");
                    pics.add("3");
                    pics.add("4");
                    pics.add("5");
                    mItem.setPics(pics);
                }
            }
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_item_detail,
                    container, false);
            DetailViewHolder holder = new DetailViewHolder();
    
            pager = (ViewPager) rootView.findViewById(R.id.pager);
            ImagePagerAdapter adapter = new ImagePagerAdapter(mItem, getActivity(),
                    inflater, position);
            pager.setAdapter(adapter);
    
            holder.position = getArguments().getInt(ARG_LIST_POSITION);
            holder.ttv = (TextView) rootView.findViewById(R.id.item_title);
            holder.dtv = (TextView) rootView.findViewById(R.id.item_detail);
            holder.likeButton = (ToggleButton) rootView
                    .findViewById(R.id.item_like);
            holder.deleteButton = (Button) rootView.findViewById(R.id.item_delete);
            rootView.setTag(holder);
    
            if (mItem != null) {
    
                holder.ttv.setText(mItem.getTitle());
                holder.dtv.setText(mItem.getDescription());
                holder.likeButton.setChecked(mItem.getIsLiked());
                holder.likeButton.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ItemListActivity.lds.open();
                        ItemListActivity.lds.toggleLike(mItem.getId());
                        mItem.toggleIsLiked();
                        ItemListActivity.lds.close();
                        ItemListFragment.listDisplayHelper.toggleLiked(position);
                    }
                });
                holder.deleteButton.setOnClickListener(new OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
                        ItemListActivity.lds.open();
                        ItemListActivity.lds.removeItem(mItem.getId());
                        ItemListActivity.lds.close();
    
                        ItemListFragment.listDisplayHelper.remove(position);
                        ItemListActivity.idpa.notifyDataSetChanged();
                        // What do I do so that the FragmentStatePagerAdapter is
                        // updated and the viewpager shows the next item.
                    }
                });
            }
    
            return rootView;
        }
    
        static private class DetailViewHolder {
            TextView ttv;
            TextView dtv;
            ToggleButton likeButton;
            Button deleteButton;
            int position;
        }
    }
    

    fragment_item_detail.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp"
        tools:context="com.trial.piclist.ItemDetailFragment" >
        <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="200dip">
        </android.support.v4.view.ViewPager>
    
        <TableRow
            android:id="@+id/tableRow1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
    
            <TextView
                android:id="@+id/item_title"
                style="?android:attr/textAppearanceLarge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello"
                android:textIsSelectable="true" />
    
            <Space
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1" />
    
            <include
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                layout="@layout/controls_layout" />
        </TableRow>
    
        <ScrollView
            android:id="@+id/descScrollView"
            android:layout_width="match_parent"
            android:layout_height="0dip"
            android:layout_weight="1" >
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >
    
                <TextView
                    android:id="@+id/item_detail"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/hello" />
            </LinearLayout>
        </ScrollView>
    
    </LinearLayout>
    

    controls_layout.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="horizontal" >
    
    <ToggleButton
        android:id="@+id/item_like"
        android:layout_width="30dip"
        android:layout_height="30dip"
        android:layout_gravity="right"
        android:background="@android:drawable/btn_star"
        android:gravity="center"
        android:text="@string/like_list_item"
        android:textOff="@string/empty_text"
        android:textOn="@string/empty_text" />
    
    <Button
        android:id="@+id/item_delete"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="30dip"
        android:layout_height="30dip"
        android:background="@android:drawable/ic_menu_delete"
        android:text="@string/empty_text" />
    
    </LinearLayout>
    

    自定义PagerAdapter 的 ImagePagerAdapter.java

    public class ImagePagerAdapter extends PagerAdapter {
        LayoutInflater inflater;
        List<View> layouts = new ArrayList<>(5);
    
        // Constructors.
    
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (layouts.get(position) != null) {
                return layouts.get(position);
            }
            View layout = inflater.inflate(R.layout.detail_image, 
                ((ViewPager) container), true);
            try {
                ImageView loadSpace = (ImageView) layout
                        .findViewById(R.id.detail_image_view);
                loadSpace.setBackgroundColor(0x000000);
                loadSpace.setImageResource(R.drawable.light_grey_background);
                loadSpace.setAdjustViewBounds(true);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            layout.setTag(images.get(position));
            layouts.set(position, layout);
            return layout;
        }
    
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
        }
    
        @Override
        public int getCount() {
            return 5;
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return (((View) object).findViewById((view.getId())) != null);
        }
    
    }
    

    FragmentPagerAdapter 的 ItemDetailPagerAdapter.java

    public class ItemDetailPagerAdapter extends FragmentStatePagerAdapter {
    
        public ItemDetailPagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int position) {
            Fragment fragment = new ItemDetailFragment();
            Bundle args = new Bundle();
            args.putLong(ItemDetailFragment.ARG_ITEM_ID, ItemListFragment.getIdByPosition(position));
            args.putInt(ItemDetailFragment.ARG_LIST_POSITION, position);
            args.putBoolean(ItemDetailFragment.ARG_TWO_PANE, ItemListActivity.mTwoPane);
            fragment.setArguments(args);
            return fragment;
        }
    
        @Override
        public int getCount() {
            openDatabase();
            int c = database.getCount();
            closeDatabase();
            return c;
        }
    
        @Override
        public int getItemPosition(Object object) {
            long mId = ((ItemDetailFragment) object).getmId();
            int pos = POSITION_NONE;
            openDatabase();
            if (database.contains(mId)) {
                pos = database.getPositionById(mId);
            }
            closeDatabase();
            return pos;
        }
    }
    

    非常感谢任何帮助。谢谢:))

2 个答案:

答案 0 :(得分:0)

在你的ItemDetailFragment中,从持有者中删除viewpager,它应该直接进入返回的视图,如下所示:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_item_detail,
            container, false);

    pager = (ViewPager) rootView.findViewById(R.id.pager);
    ImagePagerAdapter adapter = new ImagePagerAdapter(mItem, getActivity(),inflater, position);
    pager.setAdapter(adapter);

    return rootView;
}

并且ViewHolder模式应该应用于PagerAdapter。

答案 1 :(得分:0)

  1. ImagePagerAdapter.java中,更正isViewFromObject方法 -

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (view == (View) object);
    }
    

    这将更正ImageView

  2. 的问题
  3. ItemDetailPagerAdapter.java中,覆盖getItemPosition方法 -

    @Override
    public int getItemPosition(Object object) {
        int ret = POSITION_NONE;
        long id = ((ItemDetailFragment) object).getId();
        openDatabase();
        if (databaseContains(id)) {
            ret = positionInDatabase(id);
        }
        closeDatabase();
        return ret;
    }
    

    删除时调用FragmentStatePagerAdapter.NotifyDataSetChanged()方法。这将使适配器在删除时自行更新。 尽管如此,FragmentStatePagerAdapter使用片段列表和存储状态来实现适配器。这也造成了麻烦。要删除它,请实现自己的碎片列表。