为什么RecyclerView ViewBinder返回不一致的宽度

时间:2017-05-25 19:34:27

标签: android android-recyclerview

这可能是禁忌,但我正在尝试动态地将视图添加到RecyclerView中。用例是以列表格式显示不同数量的填字游戏单元格。假设单元格的默认大小是一些任意数字:100。但是,如果单元格数量的长度大于容器的宽度,则单元格需要缩小以使它们适合。 screenshot of the incorrect behavior

我当时认为解决方案是将容器的宽度除以单元格的数量,并将其设置为我正在膨胀的视图的宽度,最后将膨胀的视图添加到容器中。

public class MyViewHolder extends RecyclerView.ViewHolder {
    public static final int MAX_WIDTH = 200;
    LayoutInflater layoutInflater;
    LinearLayout cellHolder;
    TextView someText;

    public MyViewHolder(View view) {
        super(view);
        layoutInflater = LayoutInflater.from(view.getContext());
        someText = (TextView) view.findViewById(R.id.sometext);
        cellHolder = (LinearLayout) view.findViewById(R.id.cell_container);
    }

    public void bind(Integer integer) {
        someText.setText(integer.toString());
        cellHolder.removeAllViews();
        int totalWidth = cellHolder.getWidth();
        Log.e("WHY", String.format("bind: Why does this width calculation not consistently work? %d", totalWidth));

        int minWidth = totalWidth / integer;
        if (minWidth == 0 || minWidth > MAX_WIDTH) {
            minWidth = MAX_WIDTH;
        }
        for( int i = 0; i < integer; i++) {
            View inflate = layoutInflater.inflate(R.layout.box, null);
            inflate.setMinimumHeight(minWidth);
            inflate.setMinimumWidth(minWidth);

            TextView textView = (TextView) inflate.findViewById(R.id.square_number);
            textView.setText(String.valueOf(integer));
            cellHolder.addView(inflate);
        }
    }
}

我已经创建了一个示例应用,以准确显示正在发生的事情。 Here是在github上的示例应用程序中演示问题的完整代码。我尝试添加measure calls,然后添加tree observer

1 个答案:

答案 0 :(得分:1)

我可以修理你的物品!
enter image description here

您希望约束框的尺寸和最大宽度,同时如果它们填充它们,则均匀地共享其父LinearLayout的宽度。对于前两个,您需要一个简单的自定义ViewGroup:

public class SquareWithMaxSize extends FrameLayout {

public static final int MAX_WIDTH = 200;

public SquareWithMaxSize(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
    int width = Math.min(MeasureSpec.getSize(widthSpec), MAX_WIDTH);
    int side = MeasureSpec.makeMeasureSpec(width,
            MeasureSpec.EXACTLY);
    super.onMeasure(side, side);
}
}

将替换为您框中的FrameLayout,然后在ViewHolder中对其进行充气,并为每个人提供相等的layout_weight。全套!

    for( int i = 0; i < integer; i++) {
        View inflate = layoutInflater.inflate(R.layout.box, null);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, minWidth);
        lp.weight = 1;
        inflate.setLayoutParams(lp);

        TextView textView = (TextView) inflate.findViewById(R.id.square_number);
        textView.setText(String.valueOf(integer));
        cellHolder.addView(inflate);
    }

很抱歉,我不知道为什么你的孩子测量结果不一致,但我希望你不再关心:)