2016-05-12 2 views
4

В моем RecyclerView мне нужно заменить часть моего элемента на свой фрагмент. Но заменяя только первый пункт в виде ресайклера. Что я делаю неправильно?Фрагмент, заменяемый в RecyclerView item

Мой контейнер (в пункте зрения ресайклера):

... 
<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(); 

... 

} 
... 
+0

Я хотел бы предложить против использования фрагмента внутри RecyclerView элемента (I я предполагаю, что это возможно, но также предполагая, что это плохая практика). Я бы обработал все виды внутри ViewHolder. –

ответ

12

Я finnaly нашел решение. Проблема в том, что я установил нормальный идентификатор контейнера. Но в режиме ресайклера необходимо установить уникальный контейнер 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(); // Мой метод by int newContainerId = 111 + (int) (Math.random() * 9999); – AkhilGite

+0

@AkhilGite Да, это сработает. Вы также можете использовать временную метку (чтобы убедиться, что идентификатор не будет повторяться). – Mikhail

3

Благодаря Mikhali, I» m, чтобы предоставить вам полный пример работы. Обратите особое внимание на комментарии в 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> 

фрагментировать

// 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

Эй! спасибо за ваше замечательное решение. Я могу делать то, что хотел, но просто столкнулся с одной проблемой. Я получаю «Ресурсы $ NotFoundException» только на последнем элементе в обзоре Recycler, отмечая, что он приходит на последнем. Я попытался увеличить и уменьшить количество элементов в режиме просмотра rc, но результат тот же. Можете ли вы помочь мне, пожалуйста. ? – nimi0112

+0

@ nimi0112 Чтобы помочь вам, мне нужно знать, когда вы получаете это исключение. Я думаю, что может быть более одного места, где вы можете его получить. 1. Возможно, вы не правильно раздуваете представление, поэтому элемент макета не найден. 2. Возможно, ресурс, который вы пытаетесь установить или найти, не найден, пожалуйста, просто проверьте, доступен ли ваш ресурс. Чтобы помочь вам, пожалуйста, отправьте трассировку стека, если это возможно, или, пожалуйста, поделитесь тем, где в коде происходит ошибка. –

+0

посмотрите здесь https://stackoverflow.com/questions/48202131/android-content-res-resourcesnotfoundexception-unable-to-find-resource-id?noredirect1_comment83385403_48202131 – nimi0112