Android如何从ListView元素打开Fragment

6
MainActivity中有一个名为MainContainer的FrameLayout。我在那里加载一个名为TrainerMyGroups的片段,其中有一个Listview,在那里我通过使用TrainerGroupsAdapter添加了一些元素(每个元素都有一些字符串)。实际上,我想通过单击列表元素来替换片段TrainerMyGroups为另一个片段(例如TrainersInfo)。
我的TrainerGroupsAdapter如下:
public class TrainerGroupsAdapter extends ArrayAdapter {

    List list = new ArrayList();

    public TrainerGroupsAdapter(Context context, int resource) {
        super(context, resource);
    }

    static class Datahandler{
        TextView name;
        TextView when;
        TextView where;
        LinearLayout ll;
    }

    @Override
    public void add(Object object) {
        super.add(object);
        list.add(object);
    }

    @Override
    public int getCount() {
        return this.list.size();
    }

    @Override
    public Object getItem(int position) {
        return this.list.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row;
        row=convertView;
        Datahandler handler;
        SharedPreferences pref = getContext().getSharedPreferences("pref", Context.MODE_PRIVATE);

        if(convertView==null){
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row= inflater.inflate(R.layout.list_mygroups,parent,false);
            handler = new Datahandler();
            handler.name =  (TextView) row.findViewById(R.id.trainermygroupslistname);
            handler.where =  (TextView) row.findViewById(R.id.trainermygroupslistwhere);
            handler.when =  (TextView) row.findViewById(R.id.trainermygroupslistwhen);
            handler.ll=(LinearLayout) row.findViewById(R.id.trainermygroupslistlayout);
            row.setTag(handler);
        }
        else {
            handler = (Datahandler)row.getTag();
        }

        TrainerGroupsDataProvider dataProvider;
        dataProvider = (TrainerGroupsDataProvider)this.getItem(position);
        handler.name.setText(dataProvider.getName());
        handler.when.setText(dataProvider.getWhen());
        handler.where.setText(dataProvider.getWhere());
        handler.ll.setBackgroundColor(Color.parseColor(pref.getString(TRANSP_KEY, "#CC") + dataProvider.getColor()));


        handler.ll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getFragmentManager().beginTransaction().replace(R.id.MainContainer, new TrainerInfo()).addToBackStack(null).commit();
            }
        });


        return row;
    }

}

它没起作用,但方法OnClick可能是好的,因为如果我将getFragmentManager().beginTransaction().replace(R.id.MainContainer, new TrainerInfo()).addToBackStack(null).commit();替换为更改一些字符串(名称,tc时)的代码,它可以工作。问题在于getFragmentMenager(),Android Studio显示消息提示我必须创建Getter,并且AS的建议是在OnClick方法中生成:

private FragmentManager fragmentManager;
public FragmentManager getFragmentManager() {
      return fragmentManager;
}

问题出在replace的第二个参数上,我收到了一个错误提示,说它必须是Fragment(我确定TrainersInfo()是Fragment,因为我在其他地方使用过它并且它可以工作)。 我该如何解决这个问题或者在另一个fragment中点击列表元素后打开fragment的最佳方法是什么?

2个回答

4

#更新2

比起在适配器中替换片段,更好的方法是告诉您的活动应该替换该片段。这可以通过实现接口来完成,在您的活动内部实现:

public class TrainerGroupsAdapter extends ArrayAdapter {
    // The interface which you have to implement in your activity
    public interface OnChangeFragmentListener {
        void changeFragment();
    }

    List list = new ArrayList();
    private OnChangeFragmentListener m_onChangeFragmentListener;

    public TrainerGroupsAdapter(Context context, int resource) {
        super(context, resource);
        m_onChangeFragmentListener = (OnChangeFragmentListener) context;
    }

    // Your other code

}

您的getView方法中的OnClickListener:
handler.ll.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Call the method which change the fragment
        m_onChangeFragmentListener.changeFragment();
    }
});

活动:

public class MainActivity extends AppCompatActivity implements TrainerGroupsAdapter.OnChangeFragmentListener {

    //...
    //  Your Other code

    // Implement the method which is called in the adapter and replace the fragment here
    @Override
    public void changeFragment() {
        getFragmentManager().beginTransaction().replace(R.id.MainContainer, new TrainerInfo()).addToBackStack(null).commit();
    }
}

#更新1

在使用getSupportFragmentManager()和getFragmentManager()方法时需要一个活动上下文。您可以将构造函数的Context参数更改为Activity,并在类中创建一个成员变量来保存该活动,以便稍后使用:

public class TrainerGroupsAdapter extends ArrayAdapter {

    List list = new ArrayList();
    private Activity m_activity;

    public TrainerGroupsAdapter(Activity context, int resource) {
        super(context, resource);
        m_activity = context;
    }
    // Your other code
}

在您的getView方法中的OnClickListener:
   handler.ll.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            m_activity.getFragmentManager().beginTransaction().replace(R.id.MainContainer, new TrainerInfo()).addToBackStack(null).commit();
        }
   });

我尝试了,但是出现了同样的问题(getSupportFragmentManager()显示为“红色”,AS建议创建getter方法,然后new Trainersinfo()的参数错误)。 - barmi
你需要一个活动上下文来获取 getFragmentManager() 和 getSupportFragmentManager()。 - TmCrafz
你的 TrainerInfo Fragment 使用了 android.support.v4.app.Fragment 还是 android.app.Fragment?你可以在 Fragment 类中的导入中看到它。 - TmCrafz
然后你必须使用 getSupportFragmentManager() 而不是 getFragmentManager()。我已经在我的答案中添加了一个更清晰的解决方案,但如果你计划实现这个更干净的实现,请先使用旧的解决方案检查它是否可以使用 getSupportFragmentManager()。 - TmCrafz
1
如果您使用getSupportFragmentManager(),则必须将“private Activity m_activity;”更改为“private AppCompatActivity m_activity;”,并将构造函数参数从“public TrainerGroupsAdapter(Activity context,int resource)”更改为“public TrainerGroupsAdapter(AppCompatActivity context,int resource)”。这仅适用于Activity类型为“AppCompatActivity”的情况。旧解决方案是指我们目前正在讨论的解决方案,新解决方案是指我的答案中的“UPDATE2”下的解决方案。 - TmCrafz
显示剩余9条评论

1
我是一名有用的助手,可以翻译文本。

我正在寻找一个类似的答案,并从一个好友和Android开发人员那里得到了一个答案。我认为这是最容易理解和实现的方法。因此,我通常会创建一个帮助类,在其中放置我的两个静态函数以打开片段(作为替换或对话框):

例如,替换一个:

public static void openFragmentReplace(Activity activity, int idOfPlacement, Fragment fragment) 
    final FragmentManager fm = ((FragmentActivity)activity).getSupportFragmentManager();
    final FragmentTransaction fragmentTransaction = fm.beginTransaction();
    fragmentTransaction.replace(idOfPlacement, fragment);
    fragmentTransaction.commit();
}

还有对话框:

public static void openFragmentAsDialog(Activity activity, DialogFragment fragment) {
    final FragmentManager fm = ((FragmentActivity)activity).getSupportFragmentManager();
    fragment.show(fm, "tag");
}

然后我只需像这样从需要的地方调用它:
Helper.openFragmentReplace(getActivity(),R.id.PlaceForFragment,FragmentClass newFrag);

这似乎是最好且最简单的方法!

希望它能够帮助到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接