android-fragments - viewPager 中 onListItemClick 的子片段行为异常

标签 android-fragments android-viewpager android-listfragment onbackpressed

我有 3 个 ListFragments 由 viewPager 处理(由 FragmentAdapter 管理)——它们工作得很好。现在,当用户单击 ListFragment #1 中的项目时,应该会打开一个包含详细信息的新片段。它以下列方式表现得很奇怪:

  1. 仅点击列表项两次打开 DetailFragment,但调试显示第一次点击确实进入了 DetailFragment,但不显示 View ( View 仍然显示当前的 ListFragment)。

  2. 第二次点击后,DetailFragment 确实显示了它的布局,但没有显示其中的元素(如 TextView 等)。

  3. 如果用户在显示 DetailFragment 时“不小心”滑动了屏幕,viewPager 会将其设置为第二个 ListFragment!只有当按下 DetailFragment View 时,viewPager 才会“重置”为正确的 ListFragment。当然,如果用户在 DetailFragment 中滑动,viewPager 的下一个 ListFragment 应该出现,DetailFragment 应该被移除。

感谢您在 Android 的片段和 View 的奇怪世界中搞混的任何提示:)

public class PlanetFragment extends ListFragment{

    LayoutInflater inflater;
    ListView list;
    ArrayList<HashMap<String, String>> planetListArray;

    HashMap<String, String> planetMap;
    Activity activity;
    Context context;

       @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.planets_tab_layout, container, false);
            inflater=(LayoutInflater)getLayoutInflater(savedInstanceState);
            activity = getActivity();
            context = PlanetFragment.this.getActivity();
            String dbTableName = "Table_Planets";
            SQLiteHelper info = new SQLiteHelper(getActivity().getBaseContext());       
            info.open();

            ArrayList<HashMap<String, String>> datafromSQL = info.getData(dbTableName);

            if(!datafromSQL.isEmpty()){ 
                planetListArray = new  ArrayList<HashMap<String, String>>();
                for (int i = 0; i<datafromSQL.size(); i++){

                    planetMap = new HashMap<String, String>();
                    planetMap.put(PLANET_ID, datafromSQL.get(i).get(KEY_PLANET_ID));
                    planetMap.put(ZODIAC_ID, datafromSQL.get(i).get(KEY_ZODIAC_ID));
                    planetMap.put(DEGREES, datafromSQL.get(i).get(KEY_DEGREES));
                    planetMap.put(CONTENT, datafromSQL.get(i).get(KEY_CONTENT));

                    planetListArray.add(planetMap);              
                }   
                info.close();
            }

          list = (ListView) v.findViewById(android.R.id.list); 
          PlanetAdapter adapter=new PlanetAdapter(getActivity(), R.layout.planets_row, planetListArray); 
          list.setAdapter(adapter);

          return v;
       }

       @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            //the dividers 
            getListView().setDivider(getResources().getDrawable(R.drawable.purplebartop));
        }

    @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            super.onListItemClick(l, v, position, id);
            HashMap<String, String> item = planetListArray.get(position);

            Bundle bundle = new Bundle();
            bundle.putSerializable("itemMap", item);
            bundle.putInt("position", position);
            Fragment frag = DetailFragment.newInstance();
            frag.setArguments(bundle);
            if (frag != null) {
                getActivity().getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.pager, frag, "frag")
                    .addToBackStack("frag")
                    .commit();
            }
        }
}



public class DetailFragment extends Fragment{

    Context context;
    Activity activity;
    TextView planetName;

    public static android.support.v4.app.Fragment newInstance() {
        DetailFragment f = new DetailFragment();
        return f;
    }

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

        inflater=(LayoutInflater)getLayoutInflater(savedInstanceState);
        View v = inflater.inflate(R.layout.dialog_details, container, false);
        activity = getActivity();
        context = DetailFragment.this.getActivity();
        planetName = (TextView)v.findViewById(R.id.planetNameExpanded);
        planetName.setText("planetX");

        return v;
    }
}

编辑: 而不是 getActivity().getSupportFragmentManager() 我也试过 getChildFragmentManager() 但它总是给出错误: getChildFragmentManager() 方法是PlanetFragment 类型未定义。

最佳答案

当你点击一个列表项时,你确实在构建一个新的细节片段,并告诉片段管理器用那个片段替换标签“frag”。但是,您并没有告诉 View 寻呼机切换到该片段。

因为您已经有一个指向您的事件的后向指针,您可以使用 findViewById 找到您的 View 寻呼机,然后调用 viewPager.setCurrentItem。

我认为您可能会通过在列表片段中构造一个新的详细信息片段来自找麻烦。当您使用 FragmentPagerAdapter 时,适配器通常会构建片段。我会通过让适配器制作片段来实现这一点,然后在您的 onListItemClick 中找到现有的详细信息片段并调用其上的方法以使用新数据对其进行配置。但也许只有 setCurrentItem 才能解决您的问题。

编辑

首先,我会编写您的 FragmentPagerAdapter,这样您就可以使用 getItem 获取现有片段,而无需每次都创建一个新片段。

public class PlanetFragmentAdapter extends FragmentPagerAdapter {
    private Fragment [] fragments = new Fragments[3];

    public PlanetFragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = fragments[position];

        if (fragment == null) {
            switch (position) {
                case 0:
                    fragment = new PlanetFragment();
                    break;
                case 1:
                    fragment = new DetailFragment();
                    break;
                case 2:
                    fragment = new MysteryFragment();
                    break;
            }
            fragments[position] = fragment;
        }
        return fragment;
    }
}

同时在您的事件中添加函数以处理您的片段:

public void setPage(int position) {
    viewPager.setCurrentItem(position);
}

public DetailFragment getDetailFragment() {
    return (DetailFragment) viewPager.getItem(1); // now it doesn't create a new instance
    // you could also use getSupportFragmentManager().findFragmentById() here
}

现在,当您单击列表片段中的项目时,您可以获取现有的详细信息片段,对其进行配置,并设置 ViewPager 以显示详细信息片段。

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    HashMap<String, String> item = planetListArray.get(position);

    Bundle bundle = new Bundle();
    bundle.putSerializable("itemMap", item);
    bundle.putInt("position", position);
    PlanetActivity pa = (PlanetActivity) activity;
    DetailFragment frag = pa.getDetailFragment();
    frag.setArguments(bundle);
    pa.setCurrentItem(1);
}

关于android-fragments - viewPager 中 onListItemClick 的子片段行为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27169138/

相关文章:

android - 当父 View 未填满整个屏幕时, fragment 中的中心项目

android - onCreate vs onCreateView 整合ActionBar-PullToRefresh

java - ListFragment OnItemClickListener

android - 无法获取 Android View 的资源 ID

android - 在 fragmentPagerAdapter 中禁用滑动? - 安卓

android - ViewPagerIndicator 在 setCurrentItem() 之后没有更新

java - Android 在 View Pager 的 Parent Activity fragment 中设置 View

java - 将字符串从 fragment 传递到非 Activity 类

android - 是否可以在将 fragment 添加到 Activity 后将参数传递给 fragment ?

java - Android:当我在 fragment 附近使用它时,在 runOnUiThread 附近出现错误