RecyclerView Recycled ViewHolder Image查看错误的大小

时间:2015-10-22 14:27:51

标签: android android-recyclerview android-viewholder android-glide

我有一个带有不同View Holders的回收者视图。

一些视图持有者拥有图像视图,我将其传递到Glide以显示图像。

问题是,当回收者视图开始回收视图时,imageview宽度/高度是回收视图的宽度/高度,然后他们会错误地显示图像。

这是我的ImageView:

<ImageView
    android:id="@+id/image"
    android:layout_marginTop="@dimen/feed_item_margin"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"/>

这被传递到Glide

Glide.with(itemView.getContext())
    .load(Uri.parse(MediaUtils
    .getMedia(feedContent).getMediaUrl()))
    .placeholder(R.drawable.placeholder)
    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
    .crossFade().into(image);

这一点很有效,直到Recyclerview开始回收,因此recyclerview中的第一个图像看起来就是这样,这就是它的外观。

enter image description here

但是,当您从项目滚动并向后滚动时,它看起来像这样:

enter image description here

因此图像变形并且不是父图像的全宽。

我希望图片视图能够包装内容,因为所有图像都是不同的高度等等。 为了测试这一点,我添加了这一行holder.setIsRecyclable(false);以防止回收这个特定的持有者和所有显示的图像,但是,正如预期的那样,这会产生刺耳的效果。

所以我尝试在OnViewRecycled方法中重置图像视图的参数,如下所示:

@Override
public void onViewRecycled(AbstractHolder viewHolder){
    super.onViewRecycled(viewHolder);

    int position = viewHolder.getAdapterPosition();
    IFeedContent content = mFeedContentList.get(position);
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    params.setMargins(0, (int) Utils.dpTopx(mContext,10),0,0);
    params.gravity = Gravity.CENTER;

    if(isImage(content)){
        viewHolder.getImageView().setImageURI(null);
        viewHolder.getImageView().setImageDrawable(null);
        viewHolder.getImageView().setImageResource(0);
        viewHolder.getImageView().setLayoutParams(params);
    }
} 

在这里我重新创建了xml中的params,但它不起作用。方法isImage()只检查对象的mimetype。

有人可以帮忙吗?这非常令人沮丧。

对此有任何帮助表示赞赏。

编辑已添加适配器

public class ContentFeedAdapter extends RecyclerView.Adapter<AbstractHolder> {

    private List<IFeedContent> mFeedContentList;
    private Context mContext;
    private Activity mMainActivity;
    private UserHomeFragment mUserHomeFragment;
    private UserStreamFragment mUserStreamFragment;
    private AbstractHolder mAbstractHolder;
    private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> mThumbnailViewToLoaderMap;
    private ArrayList<MyMediaPlayer> mMediaPlayerList = new ArrayList<>();

    public ContentFeedAdapter(Context ctx, List<IFeedContent> contentList,  Activity mainActivity, UserHomeFragment userHomeFragment, UserStreamFragment userStreamFragment){
        this.mContext = ctx;
        this.mFeedContentList = contentList;
        this.mMainActivity = mainActivity;
        this.mThumbnailViewToLoaderMap = new HashMap<YouTubeThumbnailView, YouTubeThumbnailLoader>();
        this.mUserHomeFragment = userHomeFragment;
        this.mUserStreamFragment = userStreamFragment;
    }

    @Override
    public AbstractHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        mAbstractHolder = createAbstractHolder(viewType, parent);
        return mAbstractHolder;
    }

    @Override
    public void onBindViewHolder(final AbstractHolder holder, final int position) {
        final IFeedContent content = mFeedContentList.get(position);
        holder.bindData(content);

        if((content.getMedia()!=null) && !content.getMedia().isEmpty()){
            String mimeType = MediaUtils.getMedia(content).getMimeType();
            if(mimeType.contains(mContext.getString(R.string.video)) || mimeType.contains(mContext.getString(R.string.audio)) && !mimeType.contains(mContext.getString(R.string.youtube))){
                final ProgressBar progressBar = holder.getProgress();
                final ImageView playButton = holder.getPlayImage();
                final Button retryButton = holder.getRetryImage();
                final RelativeLayout playerOverLay = holder.getPlayerOverlay();
                final ImageView mediaThumb = holder.getMediaThumbnail();

                final MyMediaPlayer player = new MyMediaPlayer(mContext, holder.getTextureView(), holder.getMediaControllerAnchor(), holder.getProgress(),
                                                                    mimeType, MyConstants.SEEK_TO_DEFAULT, retryButton, playButton, playerOverLay, mediaThumb);
                player.setRecyclerViewPosition(position);
                mMediaPlayerList.add(player);

                playButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        player.startVideo(MediaUtils.getMedia(content).getMediaUrl());
                        holder.getPlayImage().setVisibility(View.GONE);
                        progressBar.setVisibility(View.VISIBLE);
                    }
                });
            }
        }
    }

    /**
     * Release all holders used for the
     * thumbnail views
     */
    public void releaseYouTubeHolders(){
        mAbstractHolder.releaseHolders();
    }

    @Override
    public int getItemViewType(int position){
        int viewType = -1;
        //Instantiate ViewHolder Utils
        //
        viewType = ViewHolderUtils.selectViewHolder(mFeedContentList.get(position));

        return viewType;
    }



    @Override
    public int getItemCount() {
        return mFeedContentList.size();
    }

    @Override
    public void onViewRecycled(AbstractHolder viewHolder){
        super.onViewRecycled(viewHolder);

        int position = viewHolder.getAdapterPosition();
        IFeedContent content = mFeedContentList.get(position);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.setMargins(0, (int) Utils.dpTopx(mContext,10),0,0);
        params.gravity = Gravity.CENTER;

        if(isImage(content)){
            viewHolder.getImageView().setImageURI(null);
            viewHolder.getImageView().setImageDrawable(null);
            viewHolder.getImageView().setImageResource(0);
            viewHolder.getImageView().setLayoutParams(params);
        }
    }


    /**
     * Create instance of
     * compatible viewholder
     *
     * @param viewType
     * @param parent
     * @return
     */
    private AbstractHolder createAbstractHolder(int viewType, ViewGroup parent) {
        AbstractHolder holder = null;

        switch (viewType) {
            case MyConstants.HOLDER_TYPE_1:
                holder = ViewHolder_Var1.create(parent, mUserHomeFragment, mUserStreamFragment);
                break;

            case MyConstants.HOLDER_TYPE_2:
                holder = ViewHolder_Var2.create(parent, mUserHomeFragment, mUserStreamFragment);

                break;

            case MyConstants.HOLDER_TYPE_3:
                holder = ViewHolder_Var3.create(parent, mUserHomeFragment, mUserStreamFragment);
                L.i(getClass().getSimpleName(), "HOLDER 3");
                //holder.setIsRecyclable(false);
                break;

            case MyConstants.HOLDER_TYPE_4:
                holder = ViewHolder_Var4.create(parent, mUserHomeFragment, mUserStreamFragment);
                L.i(getClass().getSimpleName(), "HOLDER 4");
                break;

            case MyConstants.HOLDER_TYPE_5:
                holder = ViewHolder_Var5.create(parent, mUserHomeFragment, mUserStreamFragment);
                L.i(getClass().getSimpleName(), "HOLDER 5");
                break;

            case MyConstants.HOLDER_TYPE_6:
                holder = ViewHolder_Var6.create(parent,  mUserHomeFragment, mUserStreamFragment);
                L.i(getClass().getSimpleName(), "HOLDER 6");
                break;

            case MyConstants.HOLDER_TYPE_7:
                holder = ViewHolder_Var7.create(parent, mUserHomeFragment, mUserStreamFragment);
                L.i(getClass().getSimpleName(), "HOLDER 7");
                break;

            case MyConstants.HOLDER_TYPE_8:
                holder = ViewHolder_Var8.create(parent, mUserHomeFragment, mUserStreamFragment);
                L.i(getClass().getSimpleName(), "HOLDER 8");
                break;

            case MyConstants.HOLDER_TYPE_9:
                holder = ViewHolder_Var9.create(parent, mUserHomeFragment, mUserStreamFragment);
                break;

            case MyConstants.HOLDER_TYPE_10:
                holder = ViewHolder_Var10.create(parent, mThumbnailViewToLoaderMap, mUserHomeFragment, mUserStreamFragment);
        }
        return holder;
    }

    private boolean isImage(IFeedContent contentItem) {
        if (MediaUtils.getMedia(contentItem) != null) {
            String mimeType = MediaUtils.getMedia(contentItem).getMimeType();
            if (mimeType.contains("image")) {
                L.i(getClass().getSimpleName(), "IMAGE HERE");
                return true;
            } else {
                L.i(getClass().getSimpleName(), "NO IMAGE HERE");

            }
        }
        return false;
    }

}

编辑2 ViewHolder 3

public class ViewHolder_Var3 extends AbstractHolder {

    @Bind(R.id.text_holder1) TextView heading;
    @Bind(R.id.text_holder2) TextView body;
    @Bind(R.id.image)ImageView image;
    @Bind(R.id.tabs_layout)LinearLayout tabsLayout;
    @Bind(R.id.hot)TextView hot;
    @Bind(R.id.comments)TextView children;
    @Bind(R.id.gif_label)TextView gifTag;
    @Bind(R.id.user_name)TextView userName;
    @Bind(R.id.tag1)TextView tag1;
    @Bind(R.id.tag2)TextView tag2;
    @Bind(R.id.tag3)TextView tag3;
    @Bind(R.id.profile_pic) SimpleDraweeView profilePic;
    private boolean mEllipsize;
    private boolean mExpanded;
    private UserHomeFragment mUserHomeFragment;
    private UserStreamFragment mUserStreamFragment;

    public ViewHolder_Var3(View itemView, UserHomeFragment userHomeFragment, UserStreamFragment userStreamFragment) {
        super(itemView);
        ButterKnife.bind(this, itemView);
        mUserHomeFragment = userHomeFragment;
        this.mUserStreamFragment = userStreamFragment;

    }

    @Override
    public void bindData(final IFeedContent feedContent) {

        userName.setText(feedContent.getAuthor().getDisplayName());
        image.setImageResource(0);
        image.setImageDrawable(null);
        image.setImageURI(null);

        TextView [] tagsArray = {tag1, tag2, tag3};

        if (feedContent.getName() != null) {
            heading.setText(feedContent.getName());
        } else {
            heading.setText(feedContent.getUrl());
        }
        if (feedContent.getName() != null) {
            body.setText((feedContent.getMessage()));
        } else {
            body.setText(feedContent.getUrl());
        }

        Log.i(ViewHolder_Var3.class.getSimpleName(), "Number of lines: " + String.valueOf(body.getLineCount()));

        if(!MediaUtils.getMedia(feedContent).getMimeType().equals("image/gif")){
            gifTag.setVisibility(View.GONE);
            Glide.with(itemView.getContext()).load(Uri.parse(MediaUtils.getMedia(feedContent).getMediaUrl())).placeholder(R.drawable.placeholder).diskCacheStrategy(DiskCacheStrategy.SOURCE).crossFade().into(image);
        }else {
            Glide.with(itemView.getContext()).load(Uri.parse(MediaUtils.getMedia(feedContent).getMediaUrl())).asGif().placeholder(R.drawable.placeholder).diskCacheStrategy(DiskCacheStrategy.RESULT).crossFade().into(image);
        }

        displayProfilePic(feedContent, profilePic);

       Glide.with(itemView.getContext()).load(Uri.parse(MediaUtils.getMedia(feedContent).getMediaUrl())).placeholder(R.drawable.placeholder).diskCacheStrategy(DiskCacheStrategy.ALL).crossFade().into(image);

        if(mUserHomeFragment==null){
            userName.setEnabled(false);
            profilePic.setEnabled(false);
        }else{
            userName.setEnabled(true);
            profilePic.setEnabled(true);
        }

        userName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivityForResult(mUserHomeFragment, feedContent.getAuthor().getId(), feedContent.getParentId());
            }
        });

        profilePic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivityForResult(mUserHomeFragment, feedContent.getAuthor().getId(), feedContent.getParentId());
            }
        });


        long hotAmt = feedContent.getLikeCount() - feedContent.getDislikeCount();
        hot.setText(String.valueOf(hotAmt));
        children.setText(String.valueOf(feedContent.getChildCount()));

        List<String> tagsList = feedContent.getTags();
        populateTags(tagsList, tagsArray);

        // if (feedContent.getTags().size() > 0) addTags(tags, tabsLayout);

        ViewTreeObserver vto = body.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                ViewTreeObserver obs = body.getViewTreeObserver();
                obs.removeOnGlobalLayoutListener(this);
                Layout layout = body.getLayout();

                if(layout!=null){
                    int lines = layout.getLineCount();
                    if(lines>0){
                        if(layout.getEllipsisCount(lines-1)>0){
                            mEllipsize = true;
                        }
                    }
                }
            }
        });

        body.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mEllipsize) {
                    if (!mExpanded) {
                        ObjectAnimator animation = ObjectAnimator.ofInt(body, "maxLines", 20);
                        //animation.setInterpolator(new BounceInterpolator());

                        animation.setDuration(200).start();
                        //     Toast.makeText(itemView.getContext(), "I AM CLICKED", Toast.LENGTH_LONG).show();
                        mExpanded = true;
                    } else {
                        ObjectAnimator animation = ObjectAnimator.ofInt(body, "maxLines", 4);
                        //animation.setInterpolator(new BounceInterpolator());
                        animation.setDuration(200).start();
                        //     Toast.makeText(itemView.getContext(), "I AM CLICKED", Toast.LENGTH_LONG).show();
                        mExpanded = false;
                    }
                }
            }
        });
    }


    @Override
    public ImageView getImageView(){
        return image;
    }

    public static ViewHolder_Var3 create(ViewGroup parent, UserHomeFragment homeFragment, UserStreamFragment userStreamFragment){
        View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_content_item_layout_var3, parent, false);
        return new ViewHolder_Var3(root, homeFragment, userStreamFragment);
    }
}

5 个答案:

答案 0 :(得分:23)

添加此行

android:adjustViewBounds="true"

到布局文件中的imageview,它会自动调整图片视图的大小。

在滑行更改.crossFade().fitCenter()

答案 1 :(得分:6)

我遇到了同样的问题,我解决了它,如下所示,

Glide.with(mContext)
   .load(model.getImage())
   .asBitmap()
   .fitCenter()
   .placeholder(R.drawable.ic_placeholder)
   .error(R.drawable.ic_placeholder)
   .into(holder.ivImage);

我刚刚添加了.asBitmap()和.fitCenter(),已解决问题。

答案 2 :(得分:1)

你必须在onBindViewHolder中设置图像宽度

例如:

yourImageView.getLayoutParams().width = GetScreenWidthPx();

public int GetScreenWidthPx() {
     DisplayMetrics displayMetrics = MyApp.GetContext().getResources().getDisplayMetrics();
     return displayMetrics.widthPixels - DpToPx(your_margin_in_dp);
}

public static int DpToPx(int dp) {
    DisplayMetrics displayMetrics =
           MyApp.GetContext()
           .getResources()
           .getDisplayMetrics();
    return (int) (dp * displayMetrics.density + 0.5f);
}

答案 3 :(得分:1)

1。 将android:adjustViewBounds="true"添加到ImageView

<ImageView
    android:id="@+id/img_item_my_show_img"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:src="@drawable/backgrund_banner"/>

2.将以下代码更改为Glide

Glide.with(context).asBitmap().load(imgUrl)
        .apply(RequestOptions()
                .fitCenter()
                .placeholder(R.drawable.default_img)
                .error(R.drawable.error_img))
        .into(ImageView)

答案 4 :(得分:0)

尝试为您的recyclerview的商品ImageView赋予以下属性: android:scaleType =“ fitXY”