getWidth() 和 getHeight() 在 RecyclerView/Fragment 中返回 0

问题描述 投票:0回答:2

我在几个片段中的

RecyclerView
方法内调用
OnCreateView
的填充方法,然后将它们定向到填充提要的适配器(取决于
context
Fragment
)。

目前,我正在为用户在 feed 上上传的图像添加标签。这些标签需要

x
y
值(位置),其中是容器的百分比(在上传时设置并保存到 BaaS)。目前,像素到百分比的公式工作得很好,但是当我尝试获取容器的尺寸时,我每次都尝试过的每个选项
returns 0

RecyclerViewHolderAllFeeds(View view) {
    ...
    this.imageContainer = (RelativeLayout) view
                .findViewById(R.id.image_container);
}

标签片段: (这个函数在bind内部调用,将所有标签绑定到上传的图片上)

  float x = containerWidth - Float.parseFloat(model.getXpoints(o)) / 100 * containerWidth;
            float y = containerHeight - Float.parseFloat(model.getYpoints(o)) / 100 * containerHeight;
            Log.e("measuredWidth", "" + containerHeight + "" + containerWidth);
            Log.e("getPointX", "" + model.getXpoints(o) + "" + model.getYpoints(o));
            Log.e("x", "x" + x + "y" + y);
            tag.setX(x);
            tag.setY(y);

我现在在 OnCreateViewHolder 方法中设置了 containerWidth 的值:

RecyclerViewHolderAllFeeds holder = null;
    LayoutInflater mInflater = LayoutInflater.from(viewGroup.getContext());
    if (viewType == 1) {
        // This method will inflate the custom layout and return as viewholde
        ViewGroup mainGroup = (ViewGroup) mInflater.inflate(R.layout.feed_and_search_feed_item_row, viewGroup, false);
        holder =  new RecyclerViewHolderAllFeeds(mainGroup);
        containerWidth = getContainerWidth(holder);
        containerHeight = getContainerHeight(holder);
    } else {
        ViewGroup mainGroup = (ViewGroup) mInflater.inflate(R.layout.progress_item, viewGroup, false);
        holder =  new ProgressViewHolder(mainGroup);
    }
    return  holder;

我也在

onViewAttchedToWindow
方法中尝试过这种方式:

   @Override
   public void onViewAttachedToWindow(RecyclerViewHolderAllFeeds holder) {
       super.onViewAttachedToWindow(holder);
       containerWidth = getContainerWidth(holder);
       containerHeight = getContainerHeight(holder);
   }

但是

x
y
值又等于零。

GetContainerWidth(ViewHolderholder)方法:

 float getContainerWidth(final RecyclerViewHolderAllFeeds h) {
        final int[] width = new int[1];
        final ViewTreeObserver observer = h.imageContainer.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                width[0] = h.imageContainer.getWidth();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    h.imageContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                } else {
                    h.imageContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }
            }
        });
        return width[0];
    }

相同的逻辑也适用于

getContainerHeight(ViewHolder holder)
方法。

我也尝试过在树观察器上没有全局侦听器并且在 preDraw 参数上有侦听器。

observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                height[0] = h.imageContainer.getHeight();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    h.imageContainer.getViewTreeObserver().removeOnPreDrawListener(this);
                }
                return false;
            }
        });

日志:

E/测量的宽度和高度:0.0 0.0
E/getPointX&Y: 70.13 88.00
E/x:x 0.0 y 0.0

是否可以解决在其他地方初始化布局并收集信息并将其存储在某个地方的问题?我已经用尽了很多选择。我只是觉得我在 SO 社区中对

Fragments
RecyclerViews
的了解还不够。

任何帮助将不胜感激。

android android-fragments android-recyclerview
2个回答
6
投票

正如@Enzokie提到的,在你知道

x
的宽度和高度之后,你必须在回调中计算你的
y
imageContainer
。因此,您所需要做的就是将
OnGlobalLayoutListener
移动到
onBindViewHolder
方法,如下所示:

@Override
public void onBindViewHolder(RecyclerViewHolderAllFeeds h, int position) {
    ...
    final ViewTreeObserver observer = h.imageContainer.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                h.imageContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                h.imageContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }

            int containerWidth = h.imageContainer.getWidth();
            int containerHeight = h.imageContainer.getHeight();
            float x = containerWidth - Float.parseFloat(model.getXpoints(o)) / 100 * containerWidth;
            float y = containerHeight - Float.parseFloat(model.getYpoints(o)) / 100 * containerHeight;
            Log.e("measuredWidth", "" + containerHeight + "" + containerWidth);
            Log.e("getPointX", "" + model.getXpoints(o) + "" + model.getYpoints(o));
            Log.e("x", "x" + x + "y" + y);

            h.tag.setX(x);
            h.tag.setY(y);
            h.tag.requestLayout();
        }
    });
    ...
}

希望有帮助!


0
投票

我通过适配器的构造函数传递了屏幕宽度。

public HorizontalAdapter(HorizontalItem[] list, int screenWidth)
HorizontalAdapter adapter = new HorizontalAdapter(list, getScreenWidth())
private int getScreenWidth(){
    WindowManager windowManager = requireActivity().getWindowManager();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(displayMetrics);
    return displayMetrics.widthPixels;
}

在适配器内部

onCreateViewHolder

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.viewholder_horizontal_item, parent, false);
        ViewGroup.LayoutParams layoutParams = itemView.getLayoutParams();

        //Set to the percent you want here.
        layoutParams.width = (int) (screenWidth * 0.33f);

        itemView.setLayoutParams(layoutParams);
        return new ViewHolder(itemView);
    }
© www.soinside.com 2019 - 2024. All rights reserved.