Fragment replacing in RecyclerView item

后端 未结 2 1751
伪装坚强ぢ
伪装坚强ぢ 2020-11-28 10:37

In my RecyclerView I need replace part of my item to my fragment. But replacing only first item in recycler view. What I am doing is wrong?

My conta

相关标签:
2条回答
  • 2020-11-28 11:15

    Thanks to Mikhali, I'm able to provide to you a complete running example. Pay special attention on the comments in onBindViewHolder()

        public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewLedgerAdapter.ViewHolder>{
            private final String TAG = RecyclerViewAdapter.class.getSimpleName();
    
            private final float FINAL_OPACITY = 0.3f;
            private final float START_OPACITY = 1f;
    
            private final int ANIMATION_TIME = 500;
            private final int TYPE_ITEM = 0;
            private final int TYPE_DATE = 1;
            private final int TYPE_TRANSACTION = 2;
            private final int TYPE_PENDING = 3;
    
            private HashMap<Integer, Integer> mElementTypes;
            private List<Operation> mObjects;
            private Context mContext;
            private Utils.CURRENCIES mCurrencySelected; // Which currency is already selected
            private boolean mCurrencyFilter; // Defines if a currency is already selected to apply filter
            private Animation mAnimationUp;
            private Animation mAnimationDown;
    
            public RecyclerViewLedgerAdapter(List<Operation> objects, Context context) {
                mElementTypes = new HashMap<Integer, Integer>();
                mObjects = objects;
                mContext = context;
                mCurrencyFilter = false;
                mCurrencySelected = null;
                mAnimationUp = AnimationUtils.loadAnimation(context, R.anim.slide_up);
                mAnimationDown = AnimationUtils.loadAnimation(context, R.anim.slide_down);
            }
    
            ...
            ...
                Not needed methods
            ...
            ...
    
            @Override
            public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_element_ledger, parent, false);
                return new ViewHolder(view);
            }
    
            @Override
            public void onBindViewHolder(final ViewHolder holder, final int position) {
                Operation operation = mObjects.get(position);
                holder.setAppUserActivity(userActivityOperation);
    
                // Remember that RecyclerView does not have onClickListener, you should implement it
                holder.getView().setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        // Hide details
                        // iDetailsContainer object could be checked on inner class ViewHolder
                        if(holder.iDetailsContainer.isShown()){
                            holder.iDetailsContainer.setVisibility(View.GONE);
                        }else{
                            // Show details
                            // Get fragment manager inside our fragment
                            FragmentManager fragmentManager = ((UserActivity)mContext).getSupportFragmentManager();
    
                            // Delete previous added fragment
                            int currentContainerId = holder.iDetailsContainer.getId();
                            // Get the current fragment
                            Fragment oldFragment = fragmentManager.findFragmentById(currentContainerId);
                            if(oldFragment != null) {
                                // Delete fragmet from ui, do not forget commit() otherwise no action
                                // is going to be observed
                                ragmentManager.beginTransaction().remove(oldFragment).commit();
                            }
    
                            // In order to be able of replacing a fragment on a recycler view
                            // the target container should always have a different id ALWAYS
                            int newContainerId = getUniqueId();
                            // Set the new Id to our know fragment container
                            holder.iDetailsContainer.setId(newContainerId);
    
                            // Just for Testing we are going to create a new fragment according
                            // if the view position is pair one fragment type is created, if not
                            // a different one is used
                            Fragment f;
                            if(position%2 == 0) {
                                f = new FragmentCard();
                            }else{
                                f=new FragmentChat();
                            }
    
                            // Then just replace the recycler view fragment as usually
                            manager.beginTransaction().replace(newContainerId, f).commit();
    
                            // Once all fragment replacement is done we can show the hidden container
                            holder.iDetailsContainer.setVisibility(View.VISIBLE);
                        }
                    }
    
                    // Method that could us an unique id
                    public int getUniqueId(){
                        return (int)SystemClock.currentThreadTimeMillis();
                    }
                });
            }
    
    
            public class ViewHolder extends RecyclerView.ViewHolder{
                private View iView;
                private LinearLayout iContainer;
                public LinearLayout iDetailsContainer;
                private ImageView iOperationIcon;
                private ImageView iOperationActionImage;
                private TextView iOperation;
                private TextView iAmount;
                private TextView iTimestamp;
                private TextView iStatus;
    
                private UserActivityOperation mUserActivityOperation;
    
                public ViewHolder(View itemView) {
                    super(itemView);
                    iView = itemView;
                    iContainer = (LinearLayout) iView.findViewById(R.id.operation_container);
                    iDetailsContainer = (LinearLayout) iView.findViewById(R.id.details_container);
                    iOperationIcon = (ImageView) iView.findViewById(R.id.ledgerOperationIcon);
                    iOperationActionImage = (ImageView) iView.findViewById(R.id.ledgerAction);
                    iOperation = (TextView) iView.findViewById(R.id.ledgerOperationDescription);
                    iAmount = (TextView) iView.findViewById(R.id.ledgerOperationCurrencyAmount);
                    iTimestamp = (TextView) iView.findViewById(R.id.ledgerOperationTimestamp);
                    iStatus = (TextView) iView.findViewById(R.id.ledgerOperationStatus);
    
                    // This linear layout status is GONE in order to avoid the view to use space
                    // even when it is not seen, when any element selected the Adapter will manage the
                    // behavior for showing the layout - container
                    iDetailsContainer.setVisibility(View.GONE);
                }
    
                ...
                ...
                    Not needed methods
                ...
                ...
            }
        }
    

    Layout

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/operation_container_maximum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="11dp"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_marginTop="11dp"
        android:orientation="vertical">
    
    
        <LinearLayout
            android:id="@+id/operation_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <FrameLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="14dp">
    
                <ImageView
                    android:id="@+id/ledgerOperationIcon"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:src="@drawable/fondear" />
    
                <ImageView
                    android:id="@+id/ledgerAction"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="bottom|right"
                    android:src="@drawable/operation_trade" />
    
    
            </FrameLayout>
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:orientation="vertical"
                android:weightSum="2">
    
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center_vertical"
                    android:layout_weight="1"
                    android:orientation="horizontal">
    
                    <TextView
                        android:id="@+id/ledgerOperationDescription"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="Descripcion"
                        android:textColor="@color/ledger_desc" />
    
                    <TextView
                        android:id="@+id/ledgerOperationCurrencyAmount"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginRight="2dp"
                        android:text="5000 BTC" />
                </LinearLayout>
    
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center_vertical"
                    android:layout_weight="1"
                    android:orientation="horizontal">
    
                    <TextView
                        android:id="@+id/ledgerOperationTimestamp"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="Fecha/Hora"
                        android:textColor="@color/ledger_timestamp" />
    
                    <TextView
                        android:id="@+id/ledgerOperationStatus"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Status" />
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    
    
        <LinearLayout
            android:id="@+id/details_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
    
    
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="Something hidden" />
    
            <ImageView
                android:layout_marginTop="15dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/user_btc"
                android:layout_gravity="center_horizontal"/>
    
        </LinearLayout>
    
    </LinearLayout>
    

    Fragment

        // This is one of the fragments used in the RecyclerViewAdapterCode, and also makes a HTTPRequest to fill the
        // view dynamically, you could laso use any of your fragments.
        public class FragmentCard extends Fragment {
    
            TextView mTextView;
    
            @Override
            public void onCreate(@Nullable Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
            }
    
            @Nullable
            @Override
            public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_card, container, false);
    
                mTextView = (TextView) view.findViewById(R.id.tv_fragment_two);
                new UserActivityAsyncTask().execute();
                return view;
            }
    
            private UserActivityOperation[] asyncMethodGetPendingWithdrawals(){
                BitsoWithdrawal[] userWithdrawals = HttpHandler.getUserWithdrawals(getActivity());
                int totalWithDrawals = userWithdrawals.length;
                UserActivityOperation[] appUserActivities = new UserActivityOperation[totalWithDrawals];
                for(int i=0; i<totalWithDrawals; i++){
                    appUserActivities[i] = new UserActivityOperation(userWithdrawals[i], getActivity());
                }
                return appUserActivities;
            }
    
            private class UserActivityAsyncTask extends AsyncTask<String, Void, Integer> {
                @Override
                protected void onPreExecute() {
                    super.onPreExecute();
                }
    
                @Override
                protected Integer doInBackground(String... strings) {
                    // Precess Compound balance
                    UserActivityOperation[] compoundBalanceProcessed = asyncMethodGetPendingWithdrawals();
                    return compoundBalanceProcessed.length;
                }
    
                @Override
                protected void onPostExecute(Integer result) {
                    super.onPostExecute(result);
                    mTextView.setText(result.toString());
                }
            }
        }
    
    0 讨论(0)
  • 2020-11-28 11:23

    I finnaly found solution. The problem is I set a common container id. But in recycler view need to set unique container id for each item.

    So, my code now this:

    MyFragment fragment = MyFragment.newInstance("fragment1");
    fragmentManager.beginTransaction().replace(UNIQUE_CONTAINER_ID, fragment).commit();
    

    If someone will be useful, here is my complete code (implementation fragment in recycler view):

    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) 
    {
    
    ...
    
    // Delete old fragment
    int containerId = holder.mediaContainer.getId();// Get container id
    Fragment oldFragment = fragmentManager.findFragmentById(containerId);
    if(oldFragment != null) {
        fragmentManager.beginTransaction().remove(oldFragment).commit();
    }
    
    int newContainerId = View.generateViewId();// Generate unique container id
    holder.mediaContainer.setId(newContainerId);// Set container id
    
    // Add new fragment
    MyFragment fragment = MyFragment.newInstance("fragment1");
    fragmentManager.beginTransaction().replace(newContainerId, fragment).commit();
    
    ...
    
    }
    

    Upd.: Instead of using your own method to generate a unique id, it is recommended to use View.generateViewId()

    0 讨论(0)
提交回复
热议问题