Android:将卡片视图从一个片段发送到另一个片段

问题描述 投票:0回答:1

我需要一个夏季项目的帮助

This is my Events fragment

This is my MyList fragment

我正在使用RecyclerView + Cardview来显示事件。这个想法是,用户可以单击每张卡右侧的大加号,该卡将显示在MyList片段中。我想问一下是否可以将卡直接从一个片段转移到另一个片段吗?另外,两个片段都包含在同一活动中,这使操作变得有些棘手(我尚未找到任何可用的解决方案)。

如果不可能,另一种方法是将CardView中包含的引用类型对象转移到MyList片段。但是,这要简单得多。这是因为在适配器中按钮已膨胀,但此处未创建引用类型对象。我看过许多有关使用Parcelable接口的教程,但是,当我什至无法在适配器中创建对象时,我都不知道如何在这里实现它。引用对象是在另一个活动中创建的,并在读取和显示之前存储在Firebase中。

我将在下面附加我的EventsAdapter.java和EventsItem.java和EventsFragment.java代码,但是请告诉我是否应该包含更多代码来描述问题。

感谢您阅读我的长篇文章!


public class EventsAdapter extends RecyclerView.Adapter<EventsAdapter.EventsViewHolder> implements Filterable {
    private ArrayList<EventsItem> mEventsList;
    private ArrayList<EventsItem> mEventsListFull;
    private EventsAdapter.OnItemClickListener mListener;
    private Context mContext;
    private DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.UK);

    public interface OnItemClickListener {
        void onItemClick(int position);
    }


    //the ViewHolder holds the content of the card
    public static class EventsViewHolder extends RecyclerView.ViewHolder {

        public ImageView mImageView;
        public ImageView mAddButton;
        public TextView mTextView1;
        public TextView mTextView2;
        public TextView mTextView3;
        public TextView mTextView4;
        public TextView mTextView5;

        public EventsViewHolder(Context context, View itemView, final EventsAdapter.OnItemClickListener listener) {
            super(itemView);
            final Context context1 = context;
            mImageView = itemView.findViewById(R.id.imageView);
            mAddButton = itemView.findViewById(R.id.image_add);
            mTextView1 = itemView.findViewById(R.id.title);
            mTextView2 = itemView.findViewById(R.id.event_description);
            mTextView3 = itemView.findViewById(R.id.date);
            mTextView4 = itemView.findViewById(R.id.location);
            mTextView5 = itemView.findViewById(R.id.time);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        int position = getAdapterPosition();
                        if (position != RecyclerView.NO_POSITION) {
                            listener.onItemClick(position);
                        }
                    }
                }
            });
            mAddButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String str1 = mTextView1.getText().toString();
                    String str2 = mTextView2.getText().toString();
                    String str3 = mTextView3.getText().toString();
                    String str4 = mTextView4.getText().toString();
                    String str5 = mTextView5.getText().toString();

                    Bundle bundle = new Bundle();
                    bundle.putString("title", str1);
                    bundle.putString("event description", str2);
                    bundle.putString("date", str3);
                    bundle.putString("location", str4);
                    bundle.putString("time", str5);
                    MylistFragment mlf = new MylistFragment();
                    mlf.setArguments(bundle);
                }
            });
        }

    }

    //Constructor for EventsAdapter class. This ArrayList contains the
    //complete list of items that we want to add to the View.
    public EventsAdapter(Context context, ArrayList<EventsItem> EventsList) {
        mEventsList = EventsList;
        mContext = context;
        mEventsListFull = new ArrayList<>(EventsList); // copy of EventsList for SearchView
    }

    //inflate the items in a EventsViewHolder
    @NonNull
    @Override
    public EventsAdapter.EventsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.event_item, parent, false);
        EventsAdapter.EventsViewHolder evh = new EventsAdapter.EventsViewHolder(mContext, v, mListener);
        return evh;
    }

    @Override
    public void onBindViewHolder(@NonNull EventsAdapter.EventsViewHolder holder, int position) {
        EventsItem currentItem = mEventsList.get(position);
        holder.mImageView.setImageResource(currentItem.getProfilePicture());
        holder.mTextView1.setText(currentItem.getTitle());
        holder.mTextView2.setText(currentItem.getDescription());
        holder.mTextView3.setText(df.format(currentItem.getDateInfo()));
        holder.mTextView4.setText(currentItem.getLocationInfo());
        holder.mTextView5.setText(currentItem.getTimeInfo());
    }



    @Override
    public int getItemCount() {
        return mEventsList.size();
    }
public class EventsItem implements Occasion, Parcelable {
    //fields removed for brevity

    //constructor removed for brevity
    }

    public EventsItem() {

    }

    public EventsItem(Parcel in) {
        profilePicture = in.readInt();
        timeInfo = in.readString();
        hourOfDay = in.readInt();
        minute = in.readInt();
        locationInfo = in.readString();
        title = in.readString();
        description = in.readString();
    }

    public static final Creator<EventsItem> CREATOR = new Creator<EventsItem>() {
        @Override
        public EventsItem createFromParcel(Parcel in) {
            return new EventsItem(in);
        }

        @Override
        public EventsItem[] newArray(int size) {
            return new EventsItem[size];
        }
    };

    //getter methods have been removed for brevity
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(profilePicture);
        dest.writeString(timeInfo);
        dest.writeString(locationInfo);
        dest.writeString(title);
        dest.writeString(description);
        dest.writeString(df.format(dateInfo));
        dest.writeInt(hourOfDay);
        dest.writeInt(minute);
    }
}
public class EventsFragment extends Fragment {
    ArrayList<EventsItem> EventsItemList;
    FirebaseDatabase mDatabase;
    DatabaseReference mDatabaseReference;
    ValueEventListener mValueEventListener;
    private RecyclerView mRecyclerView;
    private RecyclerView.LayoutManager mLayoutManager;
    private EventsAdapter mAdapter;
    private View rootView;
    public FloatingActionButton floatingActionButton;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_events, container, false);
        mDatabase = FirebaseDatabase.getInstance();
        mDatabaseReference = mDatabase.getReference().child("Events");

        createEventsList();
        buildRecyclerView();

        floatingActionButton = rootView.findViewById(R.id.fab);
        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), EventsAdder.class);
                startActivity(intent);
            }
        });
        mValueEventListener = new ValueEventListener() {

            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    EventsItemList.add(snapshot.getValue(EventsItem.class));
                }
                EventsAdapter eventsAdapter = new EventsAdapter(getActivity(), EventsItemList);
                mRecyclerView.setAdapter(eventsAdapter);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        };
        mDatabaseReference.addValueEventListener(mValueEventListener);

        setHasOptionsMenu(true);
        Toolbar toolbar = rootView.findViewById(R.id.events_toolbar);
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        activity.setSupportActionBar(toolbar);
        return rootView;
    }

    public void createEventsList() {
        EventsItemList = new ArrayList<>();
    }

    public void buildRecyclerView() {
        mRecyclerView = rootView.findViewById(R.id.recyclerview);
        mLayoutManager = new LinearLayoutManager(getContext());
        mAdapter = new EventsAdapter(getActivity(), EventsItemList);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    }

}
java android android-fragments android-recyclerview android-cardview
1个回答
0
投票

如果您希望在MyListFragment中看到相同的CardView,则可以使MyListFragment包含RecyclerView,并重用相同的EventsAdapter和EventsViewHolder。唯一的不同是,您只需要使用所需的单个事件来填充适配器,而不是用数据库中所有“事件”的子代填充适配器。

此外,由于已经使您的Event类实现可拆分,因此在单击加号按钮时不需要手动创建包。

我假设您只有一个Activity,而您只想用EventsFragment替换MyListFragment。签出replacing one fragment with another的文档。

步骤1:

onItemClickListener扩展为:

public interface OnItemClickListener {    
    void onItemClick(int position);
    void onPlusButtonClick(int position);
}

并在单击加号按钮时调整EventsViewHolder构造函数中的代码,使其看起来像这样:

mAddButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (listener != null) {
            // no need to manually create the bundle here
            // you already have all the information you need
            int position = getAdapterPosition();
            if (position != RecyclerView.NO_POSITION) {
                listener.onPlusButtonClick(position);
            }
        }
    }
});

步骤2:

实施我们的新方法onPlusButtonClick。根据我们在评论中的讨论,似乎您没有在任何地方实现此接口。您可以在构造函数内将其实现到EventsAdapter

public EventsAdapter(Context context, ArrayList<EventsItem> EventsList) {
    mEventsList = EventsList;
    mContext = context;
    mEventsListFull = new ArrayList<>(EventsList); // copy of EventsList for SearchView
    mListener = new OnItemClickListener() {
        @Override
        public void onItemClick() {
            // handle clicking the entire view holder
        }

        @Override
        public void onPlusButtonClick(int position) {
            MyListFragment myListFragment = new MyListFragment();
            Event event = mEventsList.get(position);
            Bundle bundle = new Bundle();
            bundle.putExtra("event", event); // this will work due to implementing parcelable
            myListFragment.setArguments(bundle);

            // use mContext since im assuming we areinside adapter
            // if in an Activity, no need to use context to get the fragment manager
            FragmentTransaction transaction = mContext.getSupportFragmentManager().beginTransaction();

            // Replace the EventsFragment with the MyListFragment
            // and add the transaction to the back stack so the user can navigate back
            transaction.replace(R.id.fragment_container, myListFragment);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();
        }
    }
}

第3步:

在您的MyListFragmentonCreateView()方法内部:

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

    Bundle bundle = getArguments();
    Event event = bundle.getExtra("event"); // again, will work due to implementing parcelable

    // from here you should bind to a recycler view, and you can even reuse your adapter like so:
    List<EventsItem> singleEventList = new List<EventsItem>();
    singleEventList.add(event);
    EventsAdapter adapter = new EventsAdapter(getActivity(), singleEventList);

    // be sure to inflate and return your view here...
}

你应该很好!

为了简化起见,我在这里和此处都省略了一些代码。但是我希望这是可以理解的。

作为补充,在Firebase数据库侦听器中,每当数据更新时都创建一个新的EventsAdapter是一种不好的做法。相反,您应该使用新值更新适配器中的数据。为此,请在适配器内部创建一个公共方法,例如replaceEvents(List<EventsItem> newEvents),然后在内部用新事件替换mEventsList,然后调用notifyDataSetChanged()

© www.soinside.com 2019 - 2024. All rights reserved.