0

Everything work fine before i implement the json things. When i click the detail button(imageView), dialogFragment should be pop up. It is okay with the pop up, the problem is, it's generate two or more dialogFragment. Is implement json affect the viewholder? Or its related to settag gettag?

Here my code(I used api link from the tutorial) :

RecyclerAdapter :

public class MyVoteMAPOAdapter : RecyclerView.Adapter
{
    public List<string> mImageList;
    public List<MyVote_Data> mVoteData;
    Activity context;

    public event EventHandler<int> ItemClick;

    public MyVoteMAPOAdapter (Activity context, List<MyVote_Data> data)
    {
        this.context = context;
        mVoteData = data;
    }

    public override RecyclerView.ViewHolder OnCreateViewHolder (ViewGroup parent, int viewType)
    {

        View itemView = LayoutInflater.From (parent.Context).Inflate (Resource.Layout.ItemList, parent, false);
        ViewHolder vh = new ViewHolder (itemView, OnClick);

        itemView.Tag = vh;

        return vh;
    }

    public override void OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
    {
        //int item = mData[position];
        IWindowManager windowManager = context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
        ViewHolder vh = holder as ViewHolder;

        setImage (holder, position);

        //var imageBitmap = GetImageBitmapFromUrl(mVoteData[position].mPosterImage);
        vh.IVDetail.SetTag (Resource.Id.ivDetails, position);
        //vh.IVPoster.SetImageBitmap (imageBitmap);
        vh.IVDetail.SetImageResource (Resource.Drawable.ic_information);
        vh.IVVote.SetImageResource (Resource.Drawable.undi_color);


        vh.IVPoster.Click += delegate {

            Android.App.FragmentTransaction trans = context.FragmentManager.BeginTransaction();
            FullImageView fImage = FullImageView.newInstance(position);

            vh.IVPoster.SetTag(Resource.Id.ivPoster, position);

            trans.AddToBackStack(null);
            trans.Replace(Resource.Id.place_holder, fImage);
            trans.Commit();
        };

        vh.IVVote.Click += delegate {


            if(vh.IVVote.Drawable.GetConstantState().Equals(Resource.Drawable.undi_color)){
                vh.IVVote.SetImageResource(Resource.Drawable.undi_grey);
            }
            else {
                vh.IVVote.SetImageResource(Resource.Drawable.undi_color);
            }
        };

        //set a tag for the button to the current clicked position

        vh.IVDetail.Click += IVDetail_Click;
        vh.TVLike.Text = position.ToString();

    }

    public void IVDetail_Click (object sender, EventArgs e)
    {

        //retrieve the tag
        int position = (int) (((ImageView) sender).GetTag(Resource.Id.ivDetails));


        dialogShow (position);
        Console.WriteLine ("KELUARRRRRR!~");
    }

    public void dialogShow(int position)
    {
        Android.App.FragmentTransaction transaction = context.FragmentManager.BeginTransaction();
        //instantiate a fragment
        DetailDialogFragment dialogFragment = DetailDialogFragment.newInstance (mVoteData[position].mName, mVoteData[position].mDescription);
        dialogFragment.Show (transaction, "dialog_Fragment");
    }

    //
    public async void setImage(RecyclerView.ViewHolder holder, int position)
    {
        ViewHolder vh = holder as ViewHolder;

        string tempImageString = mVoteData[position].mPosterImage;
        var imageBMP = GetImageBitmapFromUrl (tempImageString);
        //vh.IVPoster.SetImageBitmap (imageBMP);
        vh.IVPoster.SetTag (Resource.Id.ivPoster, position);
        if (imageBMP.IsCompleted) {
            vh.IVPoster.SetImageBitmap (imageBMP.Result);
        } else {
            vh.IVPoster.SetImageBitmap (await imageBMP);
        }


    }
    //decode string into bitmap
    public async static Task<Bitmap> GetImageBitmapFromUrl(string url)
    {
        Bitmap imageBitmap = null;

        try{
            if (url != null)
                using (var webClient = new WebClient ()) {
                    var imageBytes = await webClient.DownloadDataTaskAsync (url);
                    if (imageBytes != null && imageBytes.Length > 0) {
                        imageBitmap = BitmapFactory.DecodeByteArray (imageBytes, 0, imageBytes.Length);
                    }
                }
        }
        catch (Exception e){
            Console.WriteLine ("Image Exception : {0}", e);
        }
        return imageBitmap;
    }

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

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

public class ViewHolder : RecyclerView.ViewHolder
{
    public ImageView IVPoster { get; private set; }
    public TextView TVLike { get; private set; }
    public ImageView IVDetail { get; private set; }
    public ImageView IVVote { get; private set; }

    public ViewHolder (View itemView, Action<int> listener) : base(itemView)
    {
        IVPoster = itemView.FindViewById <ImageView>(Resource.Id.ivPoster);
        TVLike = itemView.FindViewById <TextView>(Resource.Id.tvLike);
        IVDetail = itemView.FindViewById <ImageView> (Resource.Id.ivDetails);
        IVVote = itemView.FindViewById <ImageView> (Resource.Id.ivVote);

        itemView.Click += (sender, e) => listener (base.Position);
    }
}

}

Child_Data.cs :

public class MyVote_Data
{
    public string mPosterImage { get; set; }
    public string mName { get; set; }
    public string mDescription { get; set; }

    public MyVote_Data ()
    {

    }

    public MyVote_Data(string image, string name, string description)
    {
        mPosterImage = image;
        mName = name;
        mDescription = description;
    }

    public List<MyVote_Data> GetVoteData( string jsonString)
    {
        string tempImage, temptName, tempDescription;

        var myVoteData = new List<MyVote_Data> ();

        var data = JsonConvert.DeserializeObject <RootObject2> (jsonString);

        foreach (var tempData in data.actors)
        {
            tempImage = tempData.image;
            temptName = tempData.name;
            tempDescription = tempData.description;

            myVoteData.Add (new MyVote_Data(tempImage, temptName, tempDescription));
        }

        return myVoteData;
    }

}

public class Actor
{
    public string name { get; set; }
    public string description { get; set; }
    public string dob { get; set; }
    public string country { get; set; }
    public string height { get; set; }
    public string spouse { get; set; }
    public string children { get; set; }
    public string image { get; set; }
}

public class RootObject2
{
    public List<Actor> actors { get; set; }
}
user3057414
  • 41
  • 1
  • 9

1 Answers1

1

There is one issue that I see that sticks out:

vh.IVPoster.Click += delegate {

            Android.App.FragmentTransaction trans = context.FragmentManager.BeginTransaction();
            FullImageView fImage = FullImageView.newInstance(position);

            vh.IVPoster.SetTag(Resource.Id.ivPoster, position);

            trans.AddToBackStack(null);
            trans.Replace(Resource.Id.place_holder, fImage);
            trans.Commit();
        };

Every time your re-use your view holder, it still contains the contents of the previous view holder. What you're doing there is your adding an addtional click event handler for every view holder. That is why you're seeing multiple dialog fragments.

What you have to do is unregister the vh.IVPoster.Click event handler before you assigned the new one. So what I would do is refactor your delegate code into an actual method. You can then use "-=" to unregister any previous event handlers and "+=" to register the current event handler.

Update:

I'm doing this by hand, so you'll have to put in a little effort and fix any compile errors and use some basic troubleshooting to get it to work.

So first, create a new method called OnIVPosterClicked:

private void OnIVPosterClicked(object sender, EventArgs e)
{
   Android.App.FragmentTransaction trans = context.FragmentManager.BeginTransaction();
   FullImageView fImage = FullImageView.newInstance(position);

   vh.IVPoster.SetTag(Resource.Id.ivPoster, position);

   trans.AddToBackStack(null);
   trans.Replace(Resource.Id.place_holder, fImage);
   trans.Commit();
}

Then Register your event handler instead of using a delegate:

vh.IVPoster.Click += OnIVPosterClicked;

To Unregister the event handler when ViewHolders get recycled, you'll have to override the:

public override void OnViewRecycled(Java.Lang.Object holder)
{
   //Unregister any View specific event handlers
   var viewHolder = holder as ViewHolder;
   viewHolder.IVPoster.Click -= OnIVPosterClicked;

   base.OnViewRecycled(holder);
}

That's the basic gist of it. It probably won't compile if you blindly copy and paste it into your program, so you'll have to fix those. I'm not sure why you're setting tags. With this pattern, that should eliminate the use for keeping track of tags.

SharpMobileCode
  • 938
  • 5
  • 8
  • Thanks! Oh the tag i used to get the position of the clicked image. E.g : "int position = (int) (((ImageView) sender).GetTag(Resource.Id.ivDetails));". I found this on xamarin forum. – user3057414 Jun 11 '15 at 04:17
  • 1
    On the view adapter, notice the ItemClick event that is defined. If you wire up an event handler for that it will return the position to that handler. If you need more info, just modify the event signature to return whatever you want. – SharpMobileCode Jun 11 '15 at 04:20
  • Ah okay okay. I'll read more about that. Thanks man! And one more thing, i follow the example on your blog. But i keep getting a static member and non-static member error. – user3057414 Jun 11 '15 at 04:58
  • I don't follow what your saying without more detail. – SharpMobileCode Jun 11 '15 at 13:08
  • Sorry2. Above is the code that i used, then i found your blog and i try to use the Task, sharedCode and async/await like yours. As u can see in the code, i retrieve the data from the json string. After i change the code, i keep getting non-static member and static member. i don't know what cause of it. So, i decide to change it back. Before this, the code is running fine, except for the duplicate fragment things. But after i try your code, i find that there is problem with convert string to bitmap. http://imgur.com/eIhINcv – user3057414 Jun 12 '15 at 03:46
  • I'm not understanding what you mean when you say " i keep getting non-static member and static member". And then you say, "i find that there is problem with convert string to bitmap". But you don't tell me any details on what errors, stack traces, etc that you have. Are these compile errors, run time errors? What error messages are you getting? I think what's happening is that you may be copy/pasting other code together that was not meant to work together and expecting it to work. You'll need to run your code through the debugger and make the proper adjustments as necessary. – SharpMobileCode Jun 12 '15 at 14:45