jjzjj

android - RecyclerView 回收 ViewHolder Image View 尺寸错误

coder 2023-11-28 原文

我有一个包含不同 View Holder 的回收站 View 。

几个 View 持有者有 ImageView ,我将它们传递给 Glide 以显示图像。

问题是,当回收器 View 开始回收 View 时, ImageView 的宽度/高度是回收 View 的宽度/高度,然后它们会错误地显示图像。

这是我的 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 中的第一张图片看起来像这样,这就是它的外观。

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

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

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

然后我尝试在 OnViewRecycled 方法中重置 ImageView 的参数,如下所示:

@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 中重新创建了参数,但它不起作用。 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);
    }
}

最佳答案

添加这一行

android:adjustViewBounds="true"

对于布局文件中的imageview,它会自动调整 ImageView 的大小。

在滑动中将 .crossFade() 更改为 .fitCenter()

关于android - RecyclerView 回收 ViewHolder Image View 尺寸错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33283493/

有关android - RecyclerView 回收 ViewHolder Image View 尺寸错误的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  3. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  4. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  5. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  6. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  7. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  8. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  9. arrays - 这是 Ruby 中 Array.fill 方法的错误吗? - 2

    这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]

  10. ruby-on-rails - Ruby on Rails 计数器缓存错误 - 2

    尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot

随机推荐