如何为android recyclerview中的最大字符串设置textview高度? [英] How to set textview height for the largest string in android recyclerview?

查看:22
本文介绍了如何为android recyclerview中的最大字符串设置textview高度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Horizo​​ntal recyclerview 和适配器,在那个图片里面,然后在标题下面,然后在下面的描述.现在所有元素的图像和标题长度几乎相同,但描述可能会有所不同.所有数据均来自 API.

现在我想要做的是,我想设置所有textview-description元素的高度,其中描述长度的数量最多.

类似于这个问题:

以前的解决方案我已经为您的问题创建了解决方案并在 GitHub 中提交

I have a Horizontal recyclerview and adapter, inside that image, then below title and then below description is there. now image and title length will be almost same for all elements but the desc may vary. All data is coming from API.

Now what I want to do is, I want to set the height of all textview-description elements, which has the highest number of description length.

Similar to this que: How to set recycler height to highest item in recyclerView?

But my question is diff, I'm just talking about desc textview and not the whole recycleeview.

Please note: It's okay that for one cardview below empty space is showing because of small desc, but make sure desc should be cover in cardview which has highest string length.

Code:

public class RecommendationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private final int VIEW_TYPE = 1;
    private final Context mContext;
    private final ArrayList<Attributes> attributesArrayList;
    private final Resources mResources;
    private final BaseActivity baseActivity;
    private final OnItemClickListener listener;

    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            listener.onViewItemClicked();
        }
    };

    public RecommendationAdapter(Context mContext, ArrayList<BraAttributes> attributesArrayList, OnItemClickListener listener) {
        this.mContext = mContext;
        this.attributesArrayList = attributesArrayList;
        mResources = mContext.getResources();
        baseActivity = (BaseActivity) mContext;
        this.listener = listener;
    }


    @NotNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
        View itemLayoutView;
        if (viewType == VIEW_TYPE) {
            itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recommend_item_layout, null);
            return new ChildViewHolderItem(itemLayoutView);
        }
        throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewholder, int position) {
        if (getItemViewType(position) == VIEW_TYPE) {
            ChildViewHolderItem holder = (ChildViewHolderItem) viewholder;
            final Attributes attributes = attributesArrayList.get(position);
            holder.ctvTitle.setText(attributes.getName());
            holder.ctvDescription.setText(attributes.getMessage());
            setImage(attributes, holder);
        }
    }

    private void findLargestString(ArrayList<attributes> attributesArrayList, CustomTextView textView) {
        String res = "";
        int largestString = attributesArrayList.get(0).getMessage().length();

        for (int i = 0; i < attributesArrayList.size(); i++) {
            if (attributesArrayList.get(i).getMessage().length() > largestString) {
                largestString = attributesArrayList.get(i).getMessage().length();
                res = attributesArrayList.get(i).getMessage();
            }
        }
        LogUtils.d("Largest String: " + res);
        setTextViewHeight(textView, res);
    }

    private void setImage(Attributes attributes, ChildViewHolderItem holder) {
        if (attributes.getImage().length() > 0) {
            Glide.with(holder.ivImage.getContext())
                    .load(IMAGE_SERVER_URL + "/medium.jpg")
                    .apply(new RequestOptions().error(R.drawable.default_load_image)
                            .placeholder(R.drawable.default_load_image))
                    .into(holder.ivImage);
        }
    }

    private int getHeight(Context context, CharSequence text, int textSize, int deviceWidth, Typeface typeface, int padding) {
        CustomTextView textView = new CustomTextView(context);
        textView.setPadding(padding, 0, padding, 0);
        textView.setTypeface(typeface);
        textView.setText(text, TextView.BufferType.SPANNABLE);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        textView.measure(widthMeasureSpec, heightMeasureSpec);
        return textView.getMeasuredHeight();
    }

    private void setTextViewHeight(CustomTextView ctvDescription, String largestString) {
        int deviceWidth;
        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(displayMetrics);
        deviceWidth = displayMetrics.widthPixels;
        LogUtils.d("deviceWidth: " + deviceWidth); //1080

        int padding = mContext.getResources().getDimensionPixelSize(R.dimen.dimen_15);

        int height = getHeight(mContext, largestString,
                mContext.getResources().getDimensionPixelSize(R.dimen.textsize_12),
                deviceWidth, Typeface.DEFAULT, padding);

        ctvDescription.setHeight(AppUtils.pxToDp(mContext, height));
    }

    @Override
    public int getItemCount() {
        return Math.max(attributesArrayList.size(), 0);
    }

    @Override
    public int getItemViewType(int position) {
        return VIEW_TYPE;
    }

    public class ChildViewHolderItem extends RecyclerView.ViewHolder {
        @BindView(R.id.ivImage)
        AppCompatImageView ivImage;
        @BindView(R.id.ctvTitle)
        CustomTextView ctvTitle;
        @BindView(R.id.ctvDescription)
        CustomTextView ctvDescription;


        public ChildViewHolderItem(View v) {
            super(v);
            ButterKnife.bind(this, v);
            v.setOnClickListener(onClickListener);
            findLargestString(attributesArrayList, ctvDescription);
        }
    }

}

In above code, description is cutting from bottom!

解决方案

Updated

Updating the answer to more to reporter request, as she wants to show all the view in the same height and of highest height as per largest description.

I have done a few tweeks in the code.

Created a method to calculate the projected height of textView by trying all the description in the list to get the highest height.

 public static int getHeightOfLargestDescription(final Context context, final CharSequence text, TextView textView) {
    final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    final Point displaySize = new Point();
    wm.getDefaultDisplay().getSize(displaySize);
    final int deviceWidth = displaySize.x;
    textView.setTypeface(Typeface.DEFAULT);
    textView.setText(text, TextView.BufferType.SPANNABLE);
    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    textView.measure(widthMeasureSpec, heightMeasureSpec);
    return textView.getMeasuredHeight();
}

then used this method to in onCreateViewHolder to get ready with the highest height to be used while binding the view.

        MyViewHolder myViewHolder = new MyViewHolder(itemView);
    for (Model m : modelList) {
        currentItemHeight = getHeightOfLargestDescription(context, m.description, myViewHolder.description);
        if (currentItemHeight > highestHeight) {
            highestHeight = currentItemHeight;
        }
    }

Then used this highestHeight in onBindViewHolder` to set the height of the description TexView, so that all the views always have the same height that is equal to the highest height.

 viewHolder.description.setHeight(highestHeight);

Code is committed in the same repo

Previous Solution I have created the solution for your problem and committed in GitHub https://github.com/dk19121991/HorizontalRecyclerWithDynamicHeight

Let me share the little bit gist of the solution

You can get the height of the description view onBindViewHolder and store that to check for if that's highest or not and always set the height of the new view with the highest height you got till now.

viewHolder.description.post(new Runnable() {
            @Override
            public void run() {
                currentItemHeight = viewHolder.description.getMeasuredHeight();
                if (currentItemHeight > highestHeight) {
                    highestHeight = currentItemHeight;
                    /** this is needed to make sure already inflated view with small description also get resized to largest view till now
                     *and this be called only if the new view is of larger size then all of the view inflated till now
                     */
                    notifyDataSetChanged();
                }
                viewHolder.description.setHeight(highestHeight);
            }
        });

You might have the question what if the older views which are already created are smaller and the new view which is going to be treated will be larger due to the large description.

No worry at all. To solve that I added notifyDataSetChanged(); whenever we are encountering a new highest height, this will make sure all the older view also get the new bigger height.

Click on this to see the app in action https://github.com/dk19121991/HorizontalRecyclerWithDynamicHeight/blob/master/runningSample.gif

Let me know if this solves your problem, if you have some more question feel free to ask.

Thanks

这篇关于如何为android recyclerview中的最大字符串设置textview高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆