【问题标题】:Adding child Fragment to Parent Fragment withing a ViewPager in Android在 Android 的 ViewPager 中将子片段添加到父片段
【发布时间】:2014-06-26 16:50:01
【问题描述】:

我正在开发一个有一些标签的应用程序,比如

每个选项卡都是一个片段,每个片段显示文章、类别和一些其他信息的列表视图。 我要做的是,当我从片段中的列表视图中点击一个项目时,打开一个包含完整文章或更多信息的新片段。我读过这与嵌套片段有关,并且我必须使用方法getChildFragmentManager()。我正在使用 ViewPager 在选项卡中显示我的片段,这是我的主要活动:

public class MainActivity extends FragmentActivity{
    private String tabs[]={"Tab1, Tab2,.<other Fragments>..,VideosFragment"};
    ViewPager viewPager=null;
    FragmentManager fragmentManager=getSupportFragmentManager();
    android.support.v4.app.FragmentTransaction ft=fragmentManager.beginTransaction();
    AdapterView adapterView;
    public static final int TIME_ENTRY_REQUEST_CODE=1;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager=(ViewPager)findViewById(R.id.pager);
        viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
        public void onPageSelected(int position){
            getActionBar().setSelectedNavigationItem(position);
        }
    });
    viewPager.setAdapter(new AdapterView(fragmentManager));
    viewPager.setOffscreenPageLimit(tabs.length);
    adapterView=new AdapterView(getSupportFragmentManager());
    /*initialization of the action bar: color, icon & title.*/
    final android.app.ActionBar actionbar=getActionBar();
    ColorDrawable color=new ColorDrawable(Color.parseColor("#cd853f"));
    actionbar.setBackgroundDrawable(color);
    actionbar.setTitle("Title");
    ActionBar.TabListener tabListener=new ActionBar.TabListener() {
        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {

        }   


        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            viewPager.setCurrentItem(tab.getPosition());
            ft=getFragmentManager().beginTransaction();
            //ft.replace(layouts[tab.getPosition()], (adapterView.getItem(tab.getPosition()));
            ft.commit();

        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {  

        }
    };
    /*Displaying Tabs for the app */
    for(int i=0;i<tabs.length;i++)
        actionbar.addTab(actionbar.newTab().setText(tabs[i]).setTabListener(tabListener));
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            actionbar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
}

} 编辑:当我点击列表视图的一个项目时,我想打开一个新片段,这是我的列表视图适配器:

public class ItemAdapter extends BaseAdapter implements OnItemClickListener{
Item item=new Item();
private ArrayList<Item> news=new ArrayList<Item>();
private static final int NO_PICTURE_VIEW=0;
private static final int PICTURE_VIEW=1;

public ItemAdapter(Context context,ArrayList<Item> items) {
    super();
    news.addAll(items);
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return news.size();

}

@Override
public Item getItem(int index) {
    // TODO Auto-generated method stub
    return getItem(index);
}

@Override
public long getItemId(int index) {
    // TODO Auto-generated method stub
    return index;
}

public int getViewTypeCount() {
    return 2;
}

public int getItemViewType(int position) {
    Item article=news.get(position);
    //  if(article.getImageUrl()!=null&&!article.getImageUrl().equals("")&&article.getImageUrl().indexOf("no_pic.png")==-1)//if there's no pic    
    if(article.getImage()!=null)      
        return PICTURE_VIEW;
      else
          return NO_PICTURE_VIEW;
}
@Override
public View getView(int index, View view, ViewGroup parent) {
    item=news.get(index);
    int type=getItemViewType(index);
        if(view==null){
            LayoutInflater inflater=LayoutInflater.from(parent.getContext());
            if(type==NO_PICTURE_VIEW){
                view=inflater.inflate(R.layout.item_no_picture_list,parent,false);
                TextView titleView=(TextView)view.findViewById(R.id.titleNoPicture);
                titleView.setText(item.getTitle());
            }
            else{
                view=inflater.inflate(R.layout.item_picture_list,parent,false);
                TextView titleView=(TextView)view.findViewById(R.id.titleArticle);
                ImageView image=(ImageView)view.findViewById(R.id.imageItem);
                titleView.setText(item.getTitle());
                image.setImageBitmap(item.getImage());
            }
    }

    return view;
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
    Log.d("ItemAdapter","clicked on "+position);
}

}

这是 ViewPager 中的片段之一:

public class VideosFragment extends Fragment{

static ListView listvideo;
ItemAdapter itemAdapter;
Context context;
Activity activity;
FragmentManager fm=getChildFragmentManager();
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
       super.onCreateView(inflater, container, savedInstanceState);
       View view=inflater.inflate(R.layout.videos_activity, container,false);
       listvideo=(ListView)view.findViewById(R.id.videoslist);
       context=getActivity();
       setRetainInstance(true); 
       return view;
    }

public void onViewCreated(View view, Bundle savedInstanceState){
    super.onViewCreated(view, savedInstanceState);
    ViewPager vp=(ViewPager)view.findViewById(R.id.pager);
    vp.setAdapter(new AdapterView(fm));
}

public void displayVideos(final List<Item> videos){
    try {        
         if(videos==null || videos.size()==0){
            Log.d("videos activity","the list is null!!");          
         }  
     } catch (Exception e) {
         e.printStackTrace();
     }
    for(int i=0;i<videos.size();i++){

    }
    itemAdapter=new ItemAdapter(context,(ArrayList<Item>) videos);
    listvideo.setAdapter(itemAdapter);
    listvideo.setOnItemClickListener(new OnItemClickListener(){
        @Override
        public void onItemClick(android.widget.AdapterView<?> parent,
                View view, int position, long id) {
            Log.d("HomeActivity","Tapped on "+position);
            //FragmentTransaction ft=fm.beginTransaction();
            //Fragment vp=new VideoPlayer();
            //ft.add(R.id.videoview, vp);
            ///ft.addToBackStack("VideosActivity");
            //ft.commit();
        }
    });
}   

public static class MyAdapter extends FragmentPagerAdapter {

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

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

    @Override
    public Fragment getItem(int position) {

        return new VideoPlayer();//ChildFragment
    }
}
}

fragmenttransaction 的注释行和之后的行给了我一个 NPE,所以我想我错过了一些东西。 VideoPlayer 是 ChildFragment,目前我只想能够显示没有信息的片段,只是为了知道它是如何工作的。这是我的片段适配器:

class AdapterView extends FragmentPagerAdapter{
public static int NUM_ITEMS=3;
Tab1 tab1=new Tab1();
    Tab2 tab2=new Tab2();
VideoFragment va=new VideoFragment();

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

@Override
public Fragment getItem(int i) {
    Log.d("FRAGMENT","EN: "+i);
    switch(i){
    case 0:
        return tab1;
    case 1:
        return tab2;
    case 2:
            return va;
    default:
        return null;
    }
}

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

}

我还没有找到我正在寻找的教程,所以我希望你们中的一些人可以帮助我了解它是如何工作的。我知道这是可能的,因为 Android API 4.2 允许这样做。我只想知道嵌套片段是如何工作的,以及如何按照我的应用程序需要的方式使用它们。感谢您提供任何信息,谢谢。

【问题讨论】:

  • 为什么你的片段命名为VideosActivity
  • 在这里查看我的答案stackoverflow.com/questions/13379194/… 举个小例子,我想这就是你想要的(?!)
  • 我遵循一些约定,一些有人提供给我的文件,但结构是一个片段,所有都是片段......我认为名字并不重要
  • 为了清楚起见,这确实很重要。如果其他人看过你的代码,看到一个名为VideosActivity 的类只是意识到它不是Activity 会非常令人困惑。 VideosFragment 会好很多。
  • 另外,您的列表适配器的代码不正确(ItemAdapter),您不应该在检查convertView 是否为空的if 子句中设置数据。我很惊讶您还没有看到任何行重复。我支持 kcoppock 所说的话,正确命名对于帮助其他试图帮助你的人非常重要(比如将 ViewPager 的适配器命名为 AdapterView,这是 android sdk 中一个众所周知的类,它连接到列表和网格,而不是片段)。

标签: android android-fragments fragment


【解决方案1】:

如果您想要用另一个片段替换视图页面中的片段,请查看this。但是,我建议您创建另一个 Fragment(一个容器),并将您的 viewpager 和 Fragment 移动到这个新 Fragment 中:

这样,当用户单击列表中的某个项目时,您可以将MainFragment 替换为Details Fragment

关于ChildFragmentManager(),当你有嵌套片段时使用它。如果您按照我的建议更改实现,则需要将 ChildFragmentManager 传递给 PagerAdapter:

viewPager.setAdapter(new AdapterView(getChildFragmentManager()));

关于您在VideosFragment 中注释的代码行的另一件事。让您的活动提交片段事务,而不是在片段内部进行。如需更好的解释,请阅读this

【讨论】:

  • 在建议的架构中找不到子片段管理器容器视图 ID。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2012-11-18
相关资源
最近更新 更多