2016-05-12 100 views
4

在我的RecyclerView中,我需要将我的项目的一部分替换为我的片段。但在回收站视图中仅替换仅第一项。我在做什么是错误的?在RecyclerView项目中替换片段

我的容器(在回收视图项):在RecyclerView适配器

... 
<FrameLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:id="@+id/container" /> 
... 

我的更新代码:

... 
@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 

... 

MyFragment fragment = MyFragment.newInstance("fragment1"); 
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit(); 

... 

} 
... 
+0

我会建议不要使用RecyclerView项目的内部片段(我我认为这是可能的,但也认为这是不好的做法)。我会处理ViewHolder中的所有视图。 –

回答

12

我finnaly找到解决方案。问题是我设置了一个正常的容器ID。但在回收商视图中,需要为每个项目设置唯一容器ID

所以,我的代码现在这个:

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

如果有人将是有益的,这是我的完整代码(在回收视图实现frament):

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 = GetUniqueID();// My method 
holder.mediaContainer.setId(newContainerId);// Set container id 

// Add new fragment 
MyFragment fragment = MyFragment.newInstance("fragment1"); 
fragmentManager.beginTransaction().replace(newContainerId, fragment).commit(); 

... 

} 
+0

你能解释我什么是GetUniqueID(); – AkhilGite

+0

我有取代这一行 INT newContainerId = GetUniqueID();可以通过 INT newContainerId = 111 +(int)的(的Math.random()* 9999)//我的方法 ; – AkhilGite

+0

@AkhilGite是的,它会工作。您也可以使用时间戳(以确保Id不会重复)。 – Mikhail

3

感谢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()); 
      } 
     } 
    } 
+0

嘿!感谢您的惊人解决方案。我能够做我想做的事情,但只面临1个问题,即我只在Recycler视图的最后一个项目上收到'Resources $ NotFoundException',请注意它即将出现在最后一个项目上。我曾尝试增加和减少rc视图中的项目数量,但结果相同。你能帮我解决吗? ? – nimi0112

+0

@ nimi0112为了帮助你,我需要知道你什么时候得到这个异常。我想可能有不止一个地方你可以得到它。 1.也许你没有正确地膨胀视图,所以找不到布局元素。 2.可能是您尝试设置或查找的资源未找到,请检查您的资源是否可用。为了帮助您,请尽可能提交堆栈跟踪信息,或者请在代码中分享发生错误的位置。 –

+0

看看这里https://stackoverflow.com/questions/48202131/android-content-res-resourcesnotfoundexception-unable-to-find-resource-id?noredirect=1#comment83385403_48202131 – nimi0112