0

This might be a no-no, but I'm trying to dynamically add views into a RecyclerView. The use case is to show crossword cells of varying number in a list format. Say the default size of the cells is some arbitrary number: 100. If, however, the length of the number of cells is greater than the width of the container, the cells need to shrink so that they will fit. screenshot of the incorrect behavior.

I was thinking that the solution then would be to divide the width of the container by the number of the cells, and set that as the width of the view I'm inflating and finally add the inflated view to the container.

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);
        }
    }
}

I've created a sample app to show exactly what's going on. Here is the entire code demonstrating the problem in a sample app on github. I've tried adding measure calls, and adding a tree observer

farkerhaiku
  • 259
  • 3
  • 12

1 Answers1

1

I can fix your items!
enter image description here

You want to constrain both the dimensions and the max width of your boxes, while sharing the width of their parent LinearLayout evenly if they fill it. For the first two, you need a simple custom 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);
}
}

Substitute that for the FrameLayout in your box, and then in your ViewHolder inflate them and give each one an equal layout_weight. All set!

    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);
    }

Sorry to say I don't know why you are getting inconsistent measurements of the child, but I hope you don't care anymore :)

Lisa Wray
  • 2,242
  • 16
  • 23