RecyclerView бросить и нажмите элемент

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

Это мой код:

RecyclerView Adapter

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, что предотвращает повторное обнаружение (поскольку x1 всегда равно 0).

2 ответа

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

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

  1. Создайте свой собственный слушатель кликов
  2. Позвоните слушателю, когда вы дотронетесь до предметов.
  3. Слушатель перезвонит MainActivity уведомить об изменении предмета.
  4. Одновременно будет вызвано сенсорное событие.

Я установил 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;
    }
}

Определен интерфейс клика:

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

Скриншот:

введите описание изображения здесь

Попробуйте это в своем клике

    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);
        }

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

Другие вопросы по тегам