BIW BIW - 2 months ago 9
Android Question

Android - Adding Views to Images doesn't update - onClick

Summary

When a user clicks on the

RecyclerView
item, I would like to add tags to that image from the information that has been stored in a BaaS [Sashido] (X Co-ordinates, Y Co-ordinates and Tag name). But, the problem I'm having isn't getting the position per-say. I create a toast when the image has been clicked, it shows the correct position corresponding to the view itself. (zero for the beginning, so on and so forth)

But how to update the position once the user clicks on another item in the list, so that the tags that correspond to the position in the array in Sashido, match the position in the
RecyclerView
, because at the moment the first row in the Sashido class is populating all images with that row's tags.

My assumption was to the pass the position to the
getTagInformation()
method using
getLayoutPosition()
so that when
objects.get(position)
array is called, it'll get the same position for Sashido class but it isn't. I feel the adapter must not be updating correctly after the user has clicked on a new item.

onBindViewHolder:

@Override
public void onBindViewHolder(RecyclerViewHolderPreviousPosts holder, int position) {
holder.bind(previousPostsList.get(position), listener);
}


onBind:

void bind(final PreviousPostsDataModel model, final OnItemClickListener listener) { ...

uploadedImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (count == 0) {
imageid = model.getImageId();
Toast.makeText(App.getContext(), "Image ID: " + imageid, Toast.LENGTH_SHORT).show();
Toast.makeText(App.getContext(), "Position: " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
getTagInformation(getLayoutPosition());
} else {
Log.e("qwert", "" + imageid);
imageContainer.removeAllViews();
imageContainer.addView(uploadedImage);
count = 0;
}
}
});
... }


getTagInformation:

private void getTagInformation(final int position) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("FashionFeed");
query.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
Toast.makeText(context, "" + position, Toast.LENGTH_SHORT).show();
JSONArray tagNamesArray = objects.get(position).getJSONArray("tagName");
JSONArray posXArray = objects.get(position).getJSONArray("tagPointX");
JSONArray posYArray = objects.get(position).getJSONArray("tagPointY");

for (int i = 0; i < tagNamesArray.length(); i++) {
for (int t = 0; t < tagNamesArray.length(); t++) {
tagNames.add(tagNamesArray.optString(t));
tagXPositions.add(posXArray.optString(t));
tagYPositions.add(posYArray.optString(t));

}

for (int o = 0; o < tagNamesArray.length(); o++) {
tag = new TextView(App.getContext());
tag.setX(Float.parseFloat(tagXPositions.get(o)));
tag.setY(Float.parseFloat(tagYPositions.get(o)));
tag.setText(tagNames.get(o));
tag.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tag.setMaxLines(1);
tag.setTextSize(11);
tag.setClickable(true);
tag.setHintTextColor(Color.WHITE);
tag.setTextColor(Color.WHITE);
tag.setBackgroundResource(R.drawable.tags_rounded_corners);
imageContainer.addView(tag);
count = 1;
}
}
} else {
Toast.makeText(context, "" + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}


I have also tried

public void getTagInformation(String imageid) {
ParseQuery query = ParseQuery.getQuery("FashionFeed");
query.WhereEqualTo("objectId", imageId);
....
}


with the
imageId
passed into the method and with also me manually entering an
objectId
that will match, it'll still only produce the tags that belong to that
objectId
. it just doesn't seem that this query is going through all of the objects. Just getting the tag information from that one object and then setting all the images with those tags.

if you need me to provide anymore code, I'm more than happy to.

BIW BIW
Answer

Solved the problem. It wasn't so much that the position was wrong, it was because I was trying to find the tags before I was populating the list of images due to Parse's FindInBackground() callback, it was being populated far too late.

The solution was that I got the JSONArray that contained the Tag names, x-coordindates and y co-ordinates inside the original query that was populating the original list of images. So they would execute simultaneously, then I passed the JSONArray values into the model, which then was passed to the bind() function in the Adapter.

Before, the problem was that the adapter was binding all of the tags onto every image, so when the click event happened on the image it would only add the tag to the imageContainer that was currently selected (in the current position), not any partiular view in any particular position.

This made it so every time the image was clicked it was always finding the first object in the database and assigning it to the selected image. [due to the click event triggering the getTagInformation() function). With the automation of the getTagInformation method within the Bind function of the ViewHolder, I was able to populate every image with the correct tags and further manipulate it using an onClickListener assigned to the image as shown below:

RecyclerView Holder:

public class RecyclerViewHolderPreviousPosts extends RecyclerView.ViewHolder implements View.OnClickListener {
        // View holder for gridview recycler view as we used in listview
        public TextView createdAt;
        public ImageView uploadedImage;
        public TextView caption;
        TextView number_of_likes;
        TextView number_of_comments;
        TextView number_of_tags;
        public ImageView comments;
        public RelativeLayout imageContainer;


    RecyclerViewHolderPreviousPosts(View view) {
        super(view);
        // Find all views ids
        this.createdAt = (TextView) view
                .findViewById(R.id.created_date);
        this.uploadedImage = (ImageView) view
                .findViewById(R.id.image);
        this.caption = (TextView) view
                .findViewById(R.id.caption_post);
        this.number_of_likes = (TextView) view
                .findViewById(R.id.number_of_likes);
        this.number_of_comments = (TextView) view
                .findViewById(R.id.number_of_comments);
        this.number_of_tags = (TextView) view
                .findViewById(R.id.number_of_tags);
        this.comments = (ImageView) view
                .findViewById(R.id.comments_image);
        this.imageContainer = (RelativeLayout) view
                .findViewById(R.id.image_container);
        view.setOnClickListener(this);
    }

    void bind(PreviousPostsDataModel model1, final int position) { ....
        model = previousPostsList.get(position);
        getTagInformation();
....}

    private void getTagInformation() {
        for (int o = 0; o < model.getTagSize(); o++) {
            tag = new TextView(App.getContext());
            tag.setX(Float.parseFloat(model.getXpoints(o)));
            tag.setY(Float.parseFloat(model.getYpoints(o)));
            Log.e("x", "" + tag.getX());
            Log.e("y", "" + tag.getY());
            tag.setText(model.getTagName(o));
            tag.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            tag.setMaxLines(1);
            tag.setTextSize(11);
            tag.setClickable(true);
            tag.setHintTextColor(Color.WHITE);
            tag.setTextColor(Color.WHITE);
            tag.setBackgroundResource(R.drawable.tags_rounded_corners);
            imageContainer.addView(tag);
            tags.add(tag);
        }
    }

    @Override
    public void onClick(View v) {
        if (count == 0) {
            for (int i = 0; i < tags.size(); i++) {
                tags.get(i).setVisibility(View.INVISIBLE);
            }
            count = 1;
        }
        else {
            for (int j = 0; j < tags.size(); j++) {
                tags.get(j).setVisibility(View.VISIBLE);
            }
            count = 0;
        }
    }
}

Profile Fragment [Original Query] :

private void populateSelectedUserRecyclerView(String objectid) {
        ParseQuery<ParseObject> query = ParseQuery.getQuery("FashionFeed");
        query.whereEqualTo("uploader", ParseObject.createWithoutData("_User", objectid));
        query.orderByDescending("createdAt");
        Log.e("get order", "ordered");
        query.findInBackground(new FindCallback<ParseObject>() {
            @Override
            public void done(List<ParseObject> objects, ParseException e) {
                Log.e("gets done", "gets into done");
                if(e == null) {
                    if (objects.size() > 0) {
                        Log.e("does it get here", "it got here");

                        latestPostList = new ArrayList<>();
                        for (ParseObject j : objects) {
                            JSONArray tagNamesArray = j.getJSONArray("tagName");
                            JSONArray posXArray = j.getJSONArray("tagPointX");
                            JSONArray posYArray = j.getJSONArray("tagPointY");
                            latestPostList.add(new PreviousPostsDataModel(tagNamesArray, posXArray, posYArray));
                        }
                    }
                    else {
                        no_follow_display.setVisibility(View.VISIBLE);
                        no_follow_display.setText(R.string.no_posts);
                        no_follow_display.bringToFront();
                        recyclerView.setVisibility(View.GONE);
                    }

                    adapter = new RecyclerViewAdapterPreviousPosts(getActivity(), latestPostList, listener);
                    recyclerView.setAdapter(adapter);// set adapter on recyclerview

                    adapter.notifyDataSetChanged();
                }
                else {
                    Log.e("failed", "failed" + e.getMessage());
                }
            }
        });
    }

Thanks for your help.

Comments