Set the Height of View to Make It Square By Knowing Only Its Width Weight

后端 未结 1 1036
-上瘾入骨i
-上瘾入骨i 2021-01-26 00:40

I have this scenario: A horizontal LinearLayout that fills the container and weightSum=100, and two views inside with weight of 50 each.

Now how do I make t

1条回答
  •  一整个雨季
    2021-01-26 01:25

    Now how do I make these two views square (e.g. the height must be equal to their width).

    If you have just those two views in the LinearLayout you have two options:

    1. Don't set your layout file directly as the content view, instead inflate it so you have a reference to the root from that file. Then post a Runnable on that root view, calculate the desired height and set it back to each of the two children of the LinearLayout that wraps them:

      final View v = getLayoutInflater().inflate(
              R.layout.views_specialheight, null);
      v.post(new Runnable() {
      
          @Override
          public void run() {
              setupHeight((ViewGroup) v);
          }
      });
      setContentView(v);
      

      where setupHeight() is the method:

      private void setupHeight(ViewGroup vg) {
          int count = vg.getChildCount();
          for (int i = 0; i < count; i++) {
              final View v = vg.getChildAt(i);            
              if (v instanceof LinearLayout) {
                  int width = v.getWidth();
                  LinearLayout.LayoutParams lp;
                  View one = ((LinearLayout) v).getChildAt(0);
                  lp = (LinearLayout.LayoutParams) one.getLayoutParams();
                  lp.height = width / 2;
                  one.setLayoutParams(lp);
                  View two = ((LinearLayout) v).getChildAt(1);
                  lp = (LinearLayout.LayoutParams) two.getLayoutParams();
                  lp.height = width / 2;
                  two.setLayoutParams(lp);
              }
          }
      }
      

      This method will work pretty well if you just have a wrapper ViewGroup subclass that wraps those LinearLayout rows. It can(and should) be improved, but I'm sure you get the point.

    2. The second option is to use a custom ViewGroup(this may be used depending on what you were planing to do with the LinearLayout) instead of the LinearLayout like this:

      
      
         

    The SpecialHeightViewGroup is a class like this:

    class SpecialHeightViewGroup extends ViewGroup {
    
    public SpecialHeightViewGroup(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }
    
    public SpecialHeightViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public SpecialHeightViewGroup(Context context) {
        super(context);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode == MeasureSpec.EXACTLY
                || widthMode == MeasureSpec.AT_MOST) {
            measureChildren(MeasureSpec.makeMeasureSpec(widthSize / 2,
                    MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                    widthSize / 2, MeasureSpec.EXACTLY));
            measureChildren(MeasureSpec.makeMeasureSpec(widthSize / 2,
                    MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                    widthSize / 2, MeasureSpec.EXACTLY));
            setMeasuredDimension(widthSize, widthSize / 2);
        } else {
            widthSize = 800; // we don't have restrictions, make it as big as we want
            measureChildren(MeasureSpec.makeMeasureSpec(widthSize / 2,
                    MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                    widthSize / 2, MeasureSpec.EXACTLY));
            measureChildren(MeasureSpec.makeMeasureSpec(widthSize / 2,
                    MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                    widthSize / 2, MeasureSpec.EXACTLY));
            setMeasuredDimension(widthSize, 400);
        }       
    }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {      
        View one = getChildAt(0);
        one.layout(0, 0, getWidth() / 2, getHeight());
        View two = getChildAt(1);
        two.layout(getWidth() / 2, 0, getWidth(), getHeight());     
    }
    
    }
    

    The custom class isn't properly tested so it may have bugs(it's just an example).

    Offtopic: Are you trying by any chance to create an UI like on the new Windows phones(with the tiles thing)?

    0 讨论(0)
提交回复
热议问题