当前位置: 首页 > 知识库问答 >
问题:

Android:将cardview从一个片段发送到另一个片段

易奇希
2023-03-14

我需要一些暑期项目的帮助

这是我的事件片段

这是我的MyList片段

我正在使用RecyclerViewCardView显示事件。其想法是,用户可以单击每张卡片右侧的大加号,卡片将显示在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());
    }

}

共有1个答案

齐乐逸
2023-03-14

如果您想在MyListFraank中看到相同的CardView,您可以让MyListFraank包含一个RecyclerView,并重用相同的EventsAdapter和EventsViewHolder。唯一的区别是,您不会使用数据库中“事件”的所有子级填充适配器,您只会使用您想要的单个事件填充它。

此外,由于您已使类实现可包裹,因此在单击加号按钮时无需手动创建捆绑包。

我假设您有一个活动,并且您只想将EventsFraank替换为MyListFraank。检查文档以用另一个片段替换一个片段。

步骤1:

将您的onItemClickListener扩展为:

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

并在单击加号按钮时,将EventsViewer中的代码调整为如下所示:

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步:

在plusButtonClick上实现我们的新方法。根据我们在评论中的讨论,您似乎没有在任何地方实现此接口。您可以在构造函数内将其实现到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
            // NOTE: inside your EventsViewHolder, it looks like you call this method on the entire itemView. This could 'swallow' the click on the plus button. You may need to adjust your code to handle this.
        }

        @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:

在MyListFragment方法中:

@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是不好的做法。相反,您应该使用新值更新适配器中的数据。通过在适配器中创建一个公共方法来做到这一点,例如replace eEvents(列表

 类似资料:
  • 这是我完整的logcat: 在Android.support.v4.app.backStackRecord.doaddop(backStackRecord.java:414)在Android.support.v4.app.backStackRecord.replace(backStackRecord.java:449)在Android.support.v4.app.backStackRecord.

  • 我知道的一种方法是通过活动。我们可以将数据从一个片段发送到另一个活动,再从一个活动发送到另一个片段。还有其他方法吗?

  • 先生/女士,我想使用android JAVA将一个片段回调到另一个片段。我试图找到问题,但没有找到解决方案。若我使用接口,它会向活动发送回调响应,这是我不想要的。非常感谢。

  • 我有两个活动,在活动1中有碎片,在活动2中有碎片 fragment1和fragment2扩展自FragmentActivity1,activity2扩展自AppCompatActivity 我想将字符串值从fragment1发送到fragment2,而不获取空值。我希望你能理解这个问题。谢谢

  • 我试着从一个片段到主要片段。编译器不喜欢我的代码,但我不确定是什么问题。转换片段的最佳实践是什么? //这是我要导航到的主片段的xml 2019-07-12 17:49:45.091 959 4-9594/com.example.cribb E/AndroidRuntime:致命异常:主进程:com.example.cribb,PID:9594 Android.content.res.resour

  • 问题内容: 我是Android的新手,这是我的第二个应用程序。我正在创建一个选项卡式活动,其中第一个片段具有创建新任务的形式,第二个片段具有所有已保存任务的列表,第三个片段从第二个列表中选择时将显示任务注释分段。第三个片段也应该像一个聊天活动,当您键入评论并点击发送按钮时,它会发布评论。当我从另一个地方(在下面的链接的GitHub分支中)实施此聊天活动时,该应用程序将完全按预期运行。但是,当我尝试