0

У меня есть RecyclerView, у которого есть сетка предметов. При нажатии на элемент он выделяется.
Я также хочу, чтобы, когда пользователь переместился прямо, вызывается метод 'next', и когда пользователь перебирает левый, вызывается метод 'previous'.
Однако они не работают друг с другом, так как каждый перехватывает события другого.
Как заставить их работать вместе?RecyclerView fling и item click

Это мой код:

RecyclerView адаптер

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) 
    { 
     myHolder = holder as MyView; 
     myHolder.mMainView.SetOnClickListener(this); 
     if (selected_position == position) 
     { 
      holder.ItemView.SetBackgroundColor(Color.LightGray); 
     } 
     else 
     { 
      holder.ItemView.SetBackgroundColor(Color.Transparent); 
     } 
    } 

public void OnClick(View v) 
    { 
     int position = mRecyclerView.GetChildLayoutPosition((View)sender); 

     // Updating old as well as new positions 
     NotifyItemChanged(selected_position); 
     selected_position = position; 
     NotifyItemChanged(selected_position); 
    } 

Фрагмент, который содержит RecyclerView

calendarRecyclerView.SetOnTouchListener(this); 

public bool OnTouch(View v, MotionEvent e) 
    { 
     switch (e.Action) 
     { 
      case MotionEventActions.Down: 
       x1 = e.GetX(); 
       break; 
      case MotionEventActions.Up: 
       x2 = e.GetX(); 
       float deltaX = x2 - x1; 
       if (Math.Abs(deltaX) > MIN_DISTANCE) 
       { 
        // Left to Right swipe action 
        if (x2 > x1) 
        { 
         NextMonth(); 
        } 

        // Right to left swipe action    
        else 
        { 
         PreviousMonth(); 
        } 
       } 


       break; 
     } 
     return false; 
    } 

Потому что я положил return false в случае OnTouch, в элемента нажмите событие запускается. Однако событие MouseDown не срабатывает в OnTouch, предотвращая обнаружение обратного пути (beacuse x1 всегда 0).

+0

Однако два не работают друг с другом, так как каждый перехватывает события другого, Вы можете объяснить больше этой линии –

+0

@OmarHossamEldin Я имел в виду, что не все события называются полностью, поскольку они «блокируют» друг друга. Внизу вопроса добавлено объяснение. Если это еще не ясно, скажите мне. – amitairos

+0

Вы можете использовать RecyclerView внутри ViewPager –

ответ

0

Попробуйте это в вашем OnClick

public void OnClick(View v) 
     { 
      int position = mRecyclerView.GetChildLayoutPosition((View)sender); 
      int oldPosition = selectedPosition; 
      selected_position = position; 
      // Updating old as well as new positions 
      NotifyItemChanged(oldPosition); 

      NotifyItemChanged(selected_position); 
     } 

Обратите внимание, что вы должны изменить выбранную позицию перед обновлением обоих пунктов

+0

Спасибо. Но проблема не в событии click. Он работает нормально. Проблема в том, что событие OnTouch вызывает первый клик, а OnClick вызывается только при втором щелчке. – amitairos

1

OnTouch событие вызывается на первый щелчок, и OnClick вызывается только при втором нажатии

MotionEventActions.Down и OnClick конфликт. В качестве обходного пути я предлагаю вам изменить цвет фона на событии MotionEventActions.Down.

  1. Создайте свой собственный нажми слушатель
  2. вызова слушателя, когда вы касаетесь вниз ваших деталей.
  3. Слушатель обратится к MainActivity, чтобы уведомить измененный элемент.
  4. В то же время вызывается событие касания.

Я поставил в viewholder OnTouchListener:

public class MyViewHolder:RecyclerView.ViewHolder,IOnTouchListener 
{ 
    private TextView textView; 
    private MyItemClickListener mListener; 
    private Context myContext; 
    float x1 = 0; 
    float x2 = 0; 
    public TextView TextView { get { return textView; } } 
    public MyViewHolder(View v, MyItemClickListener mItemClickListener) : base(v) 
    { 
     textView = v.FindViewById<TextView>(Resource.Id.itemText); 
     mListener = mItemClickListener; 
     v.SetOnTouchListener(this); 
    } 

    public MyViewHolder(View v, MyItemClickListener mItemClickListener, Context myContext) : this(v, mItemClickListener) 
    { 
     this.myContext = myContext; 
    } 
    public bool OnTouch(View v, MotionEvent e) 
    { 

     switch (e.Action) 
     { 
      case MotionEventActions.Down: 
       x1 = e.GetX(); 
       if (mListener != null) 
       { 
        mListener.OnItemClick(v, Position); 
       } 
       break; 
      case MotionEventActions.Up: 
       x2 = e.GetX(); 
       float deltaX = x2 - x1; 
       if (Math.Abs(deltaX) > 5) 
       { 
        // Left to Right swipe action 
        if (x2 > x1) 
        { 
         NextMonth(v); 
        } 

        // Right to left swipe action    
        else 
        { 
         PreviousMonth(v); 
        } 
       } 
       break; 
     } 
     return true;   
    } 

    public Boolean NextMonth(View v) 
    { 
     Toast.MakeText(myContext, "NextMonth called", ToastLength.Short).Show();  
     return true; 
    } 

    public Boolean PreviousMonth(View v) 
    { 
     Toast.MakeText(myContext, "PreviousMonth called", ToastLength.Short).Show(); 
     return true; 
    } 
} 

Defined интерфейс нажмите:

public interface MyItemClickListener 
{ 
    void OnItemClick(View view, int postion); 
} 

установить щелчок обратного вызова в MainActivity, чтобы изменить цвет фона:

public class MainActivity : Activity,MyItemClickListener 
    { 
     RecyclerView mRecyclerView; 
     RecyclerView.LayoutManager mLayoutManager; 
     CustomAdapter mAdapter; 
     string[] dataSet; 
     protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 
      InitDataSet(); 
      SetContentView(Resource.Layout.Main); 

      mLayoutManager = new LinearLayoutManager(this); 

      mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView); 
      mRecyclerView.SetLayoutManager(mLayoutManager); 
      mAdapter = new CustomAdapter(dataSet,this); 
      mAdapter.setOnItemClickListener(this); 
      mRecyclerView.SetAdapter(mAdapter); 

      //mRecyclerView.SetOnTouchListener(this); 
     } 

     public void InitDataSet() 
     { 
      dataSet = new string[60]; 
      for (int i = 0; i < 60; i++) 
      { 
       dataSet[i] = "This is element #" + i; 
      } 
     } 

     public void OnItemClick(View view, int postion) 
     { 
      mAdapter.NotifyItemChanged(CustomAdapter.selected_position); 
      CustomAdapter.selected_position = postion; 
      mAdapter.NotifyItemChanged(postion); 
     } 
    } 
    } 

Примечание. Держите палец быстро, если скорость достаточно низкая, MotionEventActions.Down не будет вызываться.

Github souce code

Скрин:

enter image description here