[英]Fragment replacing in RecyclerView item
在我的 RecyclerView 中,我需要將我的項目的一部分替換為我的片段。 但是只替換回收者視圖中的第一項。 我在做什么是錯誤的?
我的容器(在回收商視圖項目中):
...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container" />
...
我在 RecyclerView 適配器中的更新代碼:
...
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
...
MyFragment fragment = MyFragment.newInstance("fragment1");
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
...
}
...
我終於找到了解決方案。 問題是我設置了一個通用的容器 ID。 但是在回收商視圖中需要為每個項目設置唯一的容器 ID 。
所以,我的代碼現在是這樣的:
MyFragment fragment = MyFragment.newInstance("fragment1");
fragmentManager.beginTransaction().replace(UNIQUE_CONTAINER_ID, fragment).commit();
如果有人有用,這是我的完整代碼(回收站視圖中的實現片段):
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();
...
}
更新:建議使用View.generateViewId()
代替自己的方法生成唯一id
感謝 Mikhali,我能夠為您提供一個完整的運行示例。 特別注意 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
...
...
}
}
布局
<?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>
片段
// 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());
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.