簡體   English   中英

如何處理Cardview中圖像按鈕內的單擊事件以打開彈出菜單

[英]How handle click event inside image button in a cardview for opening a popup menu

我想實現一個RecyclerView,它集成了CardViews的網格。 cardView內部有一個簡單的圖像按鈕,單擊該按鈕即可打開彈出菜單。 問題是,當我滾動幾次整個recyclerview並嘗試單擊圖像按鈕時,它顯示了多個彈出窗口。 似乎我沒有單擊多個CardView中的圖像按鈕,因為我只單擊了一個Cardview中的按鈕。 我認為問題出在圖像按鈕(在recyclerView代碼中)內的單擊偵聽器中,但是我不明白我哪里寫錯了。 在此視頻中,您可以看到失敗。 預先感謝您的幫助。

這是我的cardView示例( FotoCardView.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/foto_cardView"
        android:background="?attr/selectableItemBackground"
        android:foreground="?android:attr/selectableItemBackground"
        card_view:cardBackgroundColor="@android:color/transparent"
        card_view:cardElevation="1dp"
        card_view:cardPreventCornerOverlap="false"
        card_view:cardUseCompatPadding="true"
        card_view:cardCornerRadius="0dp">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/foto_img"
            android:scaleType="centerCrop" />
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="@android:color/black"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:paddingTop="7dp"
            android:paddingBottom="8dp"
            android:alpha="0.6">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:visibility="invisible"
                android:textSize="15sp"
                android:id="@+id/foto_caption"
                android:textColor="@android:color/white"
                android:text="#"
                android:alpha="1" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:textSize="15sp"
                android:id="@+id/foto_caption2"
                android:textColor="@android:color/white"
                android:text="left"
                android:alpha="1" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/foto_caption2"
                android:id="@+id/foto_caption3"
                android:text="IMG_data_foto.jpg"
                android:textSize="12sp"
                android:textColor="@android:color/white"
                android:alpha="1" />
            <ImageButton
                android:id="@+id/card_options"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_more_vert_white_24dp"
                android:alpha="1"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:background="?attr/selectableItemBackgroundBorderless" />
        </RelativeLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

CardFotoAdapter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V7.Widget;
using Showroom.XamarinItemTouchHelper;
using ViewHolder = Android.Support.V7.Widget.RecyclerView.ViewHolder;
using Android.Graphics;
using Android.Support.Design.Widget;
using Showroom.ORM;
using SQLite;
using Square.Picasso; // Es. la utilizza la Snackbar

namespace Showroom.Adapters
{
    public class CardFotoAdapter : RecyclerView.Adapter, IItemTouchHelperAdapter
    {
        public IList<Foto> foto;
        Context context;
        private IOnStartDragListener dragStartListener;
        public event EventHandler<int> itemClick;

        // Costruttore della classe adapter
        public CardFotoAdapter(IList<Foto> foto, Context context, IOnStartDragListener dragStartListener)
        {
            this.foto = foto;
            this.context = context;
            this.dragStartListener = dragStartListener;
        }

        // Metodo che inizializza il ViewHolder associando il layout al recyclerview
        public override ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
        {
            View fotoView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.FotoCardView, parent, false);
            ViewHolderFoto vh = new ViewHolderFoto(fotoView, OnClick);
            return vh;
        }

        // Metodo che specifica il contenuto del ViewHolder (effettua il bind dei dati)
        public override void OnBindViewHolder(ViewHolder holder, int position)
        {
            ViewHolderFoto vh = holder as ViewHolderFoto;
            // Controllo che la foto abbia una didascalia
            if (foto[position].descr != null)
            {
                vh.txtFotoCaption.Text = foto[position].descr;
            }
            // Controllo che esista un URL della foto
            if (foto[position].url != null)
            {
                Picasso.With(vh.imgFoto.Context)
                    .Load(Utils.urlImageToThumb("file://" + foto[position].url))
                    .Into(vh.imgFoto);
                //BitmapFactory.Options options = new BitmapFactory.Options();
                //options.InSampleSize = 1;
                //Bitmap myBitmap = BitmapFactory.DecodeFile(Utils.urlImageToThumb(foto[position].url), options);
                //vh.imgFoto.SetImageBitmap(myBitmap);
                ////vh.imgFoto.SetOnTouchListener(new TouchListenerHelper(vh, dragStartListener));
                //myBitmap.Dispose();
            }

            vh.imgFotoOptions.Click += (sender1, args1) =>
                {
                    Toast.MakeText(context, "test Modifica" + position.ToString(), ToastLength.Short).Show();
                    //Toast.MakeText(context, "test Modifica " + position.ToString(), ToastLength.Short).Show();
                    Android.Widget.PopupMenu popup = new Android.Widget.PopupMenu(vh.imgFotoOptions.Context, vh.imgFotoOptions);
                    popup.Inflate(Resource.Menu.CardMenu);
                    popup.MenuItemClick += (s, args) =>
                        {
                            switch (args.Item.ItemId)
                            {
                                case Resource.Id.delete:
                                    Toast.MakeText(context, "FOTO ELIMINATA", ToastLength.Short).Show();
                                    DBRepository dbr = new DBRepository();
                                    var path = dbr.pathDB();
                                    var db = new SQLiteConnection(path);
                                    db.Delete(foto[position]);
                                    db.Close();
                                    foto.RemoveAt(position);
                                    NotifyItemRemoved(position);
                                    break;
                                case Resource.Id.edit:
                                    Toast.MakeText(context, "edit " + position.ToString(), ToastLength.Short).Show();
                                    break;
                            }
                        };
                    popup.Show();
                };
            vh.txtFotoCaption2.Text = "descrizione1";
            vh.txtFotoCaption3.Text = System.IO.Path.GetFileNameWithoutExtension(foto[position].url);
        }

        void OnClick(int position)
        {
            if (itemClick != null)
                itemClick(this, position);
        }

        public override int ItemCount
        {
            get { return foto.Count; }
        }

        public void OnItemDismiss(int position, RecyclerView rv)
        {
            Snackbar
                .Make(rv, "Test snackbar", Snackbar.LengthShort)
                .Show();
            DBRepository dbr = new DBRepository();
            var path = dbr.pathDB();
            var db = new SQLiteConnection(path);
            db.Delete(foto[position]);
            db.Close();
            foto.RemoveAt(position);
            NotifyItemRemoved(position);
        }

        public bool OnItemMove(int fromPosition, int toPosition)
        {
            // Abilitare l'ordinamento
            NotifyItemMoved(fromPosition, toPosition);
            return true;
        }

        public class ViewHolderFoto : ViewHolder, IItemTouchHelperViewHolder
        {
            public View mainView { get; private set; }
            public CardView cardView { get; private set; }
            public TextView txtFotoCaption { get; private set; }
            public TextView txtFotoCaption2 { get; private set; }
            public TextView txtFotoCaption3 { get; private set; }
            public ImageView imgFoto { get; private set; }
            public ImageButton imgFotoOptions { get; private set; }

            public ViewHolderFoto(View fotoView, Action<int> listener)
                : base(fotoView)
            {
                mainView = fotoView;
                cardView = (CardView)fotoView.FindViewById<CardView>(Resource.Id.foto_cardView);
                txtFotoCaption = (TextView)fotoView.FindViewById<TextView>(Resource.Id.foto_caption);
                txtFotoCaption2 = (TextView)fotoView.FindViewById<TextView>(Resource.Id.foto_caption2);
                txtFotoCaption3 = (TextView)fotoView.FindViewById<TextView>(Resource.Id.foto_caption3);
                imgFoto = (ImageView)fotoView.FindViewById<ImageView>(Resource.Id.foto_img);
                imgFotoOptions = (ImageButton)fotoView.FindViewById<ImageButton>(Resource.Id.card_options);
                fotoView.Click += (sender, e) => listener(base.Position);
            }

            public void OnItemSelected()
            {
                //mainView.SetBackgroundColor(Color.LightGray);
                //cardView.SetCardBackgroundColor(Color.LightGray);

            }

            public void OnItemClear()
            {
                //mainView.SetBackgroundColor(Color.White);
                cardView.SetCardBackgroundColor(Color.Transparent);
            }
        }

    }
}

GalleryCardActivity.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V7.App;
using Showroom.XamarinItemTouchHelper;
using Toolbar = Android.Support.V7.Widget.Toolbar;
using Android.Support.V7.Widget;
using Showroom.ORM;
using SQLite;
using Showroom.Adapters;
using Android.Support.V7.Widget.Helper; // ItemTouchHelper.Callback

namespace Showroom.Activities
{
    [Activity(Label = "GalleryCardActivity")]
    public class GalleryCardActivity : AppCompatActivity, IOnStartDragListener
    {
        private IList<Foto> fotoVariante = new List<Foto>();
        private ItemTouchHelper itemTouchHelper;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Create your application here
            SetContentView(Resource.Layout.GalleryGrid2);
            var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
            SupportActionBar.Title = "Griglia Foto";

            // Collego il linear layout manager
            int columns = Resources.GetInteger(Resource.Integer.grid_colums);  // Il numero delle colonne cambia in base all'orientamento
            GridLayoutManager glm = new GridLayoutManager(this, columns);

            // Collego il layout manager all'adapter
            RecyclerView rv = FindViewById<RecyclerView>(Resource.Id.rvFoto);
            rv.SetLayoutManager(glm);

            int idItem = Convert.ToInt32(Intent.GetStringExtra("idItem"));

            // Imposto i dati da visualizzare
            DBRepository dbr = new DBRepository();
            fotoVariante = dbr.fotoVariante(idItem);
            CardFotoAdapter fotoAdapter = new CardFotoAdapter(fotoVariante, this, this);
            fotoAdapter.itemClick += OnItemClick;
            rv.SetAdapter(fotoAdapter);
            ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(fotoAdapter, rv);
            itemTouchHelper = new ItemTouchHelper(callback);
            itemTouchHelper.AttachToRecyclerView(rv);
        }

        void OnItemClick(object sender, int position)
        {
            Foto foto = fotoVariante.ElementAt(position);
            var uri = Android.Net.Uri.Parse("file://" + foto.url);
            Intent i = new Intent(Intent.ActionView);
            i.SetDataAndType(uri, "image/*");
            StartActivity(i);
        }

        public void OnStartDrag(RecyclerView.ViewHolder viewHolder)
        {
            itemTouchHelper.StartDrag(viewHolder);
        }

    }
}

解決方案非常簡單,因為我犯了一個簡單的錯誤! 我必須將click事件放置在“ OnCreateViewHolder”方法的內部而不是“ OnBindViewHolder”的內部。 所以看起來類似於這段代碼

        // Metodo che inizializza il ViewHolder
    public override ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.VarianteCardView, parent, false);
        ViewHolderCard vh = new ViewHolderCard(itemView, OnClick);
        // Gestisco il click del pulsante opzioni di ciascuna CardView
        vh.imgCardOptions.Click += (o, e) =>
        {
            Toast.MakeText(context, "ciao " + vh.AdapterPosition.ToString(), ToastLength.Short).Show();
            PopupMenu popup = new PopupMenu(context, vh.imgCardOptions);
            popup.Inflate(Resource.Menu.CardMenu);
            popup.MenuItemClick += (s, args) =>
            {
                switch (args.Item.ItemId)
                {
                    case Resource.Id.delete:
                        Toast.MakeText(context, "delete " + vh.AdapterPosition.ToString(), ToastLength.Short).Show();
                        break;
                    case Resource.Id.edit:
                        Toast.MakeText(context, "edit " + vh.AdapterPosition.ToString(), ToastLength.Short).Show();
                        break;
                }
            };
            popup.Show();
        };
        return vh;
    }
        // Metodo che specifica il contenuto del ViewHolder (effettua il bind dei dati)
    public override void OnBindViewHolder(ViewHolder holder, int position)
    {


        ViewHolderCard vh = holder as ViewHolderCard;
        vh.txtVarianteId.Text = varianti[position].ID.ToString();
        vh.txtVarianteModello.Text = varianti[position].codiceModello;
        vh.txtVarianteBrand.Text = varianti[position].brand;

        if (varianti[position].fotoUrl != null)
        {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.InSampleSize = 1;
            Bitmap myBitmap = BitmapFactory.DecodeFile(Utils.urlImageToThumb(varianti[position].fotoUrl), options);
            vh.imgVariantePhoto.SetImageBitmap(myBitmap);
            //vh.imgVariantePhoto.SetOnTouchListener(new TouchListenerHelper(vh, mDragStartListener)); // Rimosso perchè altrimenti il drag avviene senza long click (basta fare lo swipe sull'immagine ad avviene il drag)
            myBitmap.Dispose();
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM