[原創]android自定義控件的最大高度MaxHeightView

代碼地址:https://github.com/Carbs0126/MaxHeightViewjava

android中部分控件具備maxHeight功能,如button等,可是對於ViewGroup類的控件,沒有此屬性,當咱們須要限制某些view的高度時,(好比限制屏幕下方對話框的最大高度)那麼,就須要一種能夠限制其子view最大高度的ViewGroup。如何爲自定義ViewGroup添加一個最大高度的屬性呢?其實很簡單,主要就是使用onMeasure()函數,在函數中控制高度便可。android

先看下效果圖:git

這是一個dialog,dialog中添加了共有20個button,若是不使用最大高度可控的viewgroup,則會充滿整個屏幕。github

 

java代碼實現以下:app

 

  1 package cn.carbs.android.maxheightview.library;
  2 
  3 /**
  4  * Created by carbs on 2016/5/12.
  5  */
  6 import android.content.Context;
  7 import android.content.res.TypedArray;
  8 import android.util.AttributeSet;
  9 import android.view.WindowManager;
 10 import android.widget.FrameLayout;
 11 
 12 /**
 13  * 先判斷是否設定了mMaxHeight,若是設定了mMaxHeight,則直接使用mMaxHeight的值,
 14  * 若是沒有設定mMaxHeight,則判斷是否設定了mMaxRatio,若是設定了mMaxRatio的值 則使用此值與屏幕高度的乘積做爲最高高度
 15  *
 16  * @author Carbs
 17  */
 18 public class MaxHeightView extends FrameLayout {
 19 
 20     private static final float DEFAULT_MAX_RATIO = 0.6f;
 21     private static final float DEFAULT_MAX_HEIGHT = 0f;
 22 
 23     private float mMaxRatio = DEFAULT_MAX_RATIO;// 優先級高
 24     private float mMaxHeight = DEFAULT_MAX_HEIGHT;// 優先級低
 25 
 26     public MaxHeightView(Context context) {
 27         super(context);
 28         init();
 29     }
 30 
 31     public MaxHeightView(Context context, AttributeSet attrs) {
 32         super(context, attrs);
 33         initAttrs(context, attrs);
 34         init();
 35     }
 36 
 37     public MaxHeightView(Context context, AttributeSet attrs, int defStyle) {
 38         super(context, attrs, defStyle);
 39         initAttrs(context, attrs);
 40         init();
 41     }
 42 
 43     private void initAttrs(Context context, AttributeSet attrs) {
 44         TypedArray a = context.obtainStyledAttributes(attrs,
 45                 R.styleable.MaxHeightView);
 46 
 47         final int count = a.getIndexCount();
 48         for (int i = 0; i < count; ++i) {
 49             int attr = a.getIndex(i);
 50             if(attr == R.styleable.MaxHeightView_mhv_HeightRatio){
 51                 mMaxRatio = a.getFloat(attr, DEFAULT_MAX_RATIO);
 52             }else if(attr == R.styleable.MaxHeightView_mhv_HeightDimen){
 53                 mMaxHeight = a.getDimension(attr, DEFAULT_MAX_HEIGHT);
 54             }
 55         }
 56         a.recycle();
 57     }
 58 
 59     private void init(){
 60         if (mMaxHeight <= 0) {
 61             mMaxHeight = mMaxRatio * (float) getScreenHeight(getContext());
 62         } else {
 63             mMaxHeight = Math.min(mMaxHeight, mMaxRatio * (float) getScreenHeight(getContext()));
 64         }
 65     }
 66 
 67     @Override
 68     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 69 
 70         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 71         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 72 
 73         if (heightMode == MeasureSpec.EXACTLY) {
 74             heightSize = heightSize <= mMaxHeight ? heightSize
 75                     : (int) mMaxHeight;
 76         }
 77 
 78         if (heightMode == MeasureSpec.UNSPECIFIED) {
 79             heightSize = heightSize <= mMaxHeight ? heightSize
 80                     : (int) mMaxHeight;
 81         }
 82         if (heightMode == MeasureSpec.AT_MOST) {
 83             heightSize = heightSize <= mMaxHeight ? heightSize
 84                     : (int) mMaxHeight;
 85         }
 86         int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,
 87                 heightMode);
 88         super.onMeasure(widthMeasureSpec, maxHeightMeasureSpec);
 89     }
 90 
 91     /**
 92      * 獲取屏幕高度
 93      *
 94      * @param context
 95      */
 96     private int getScreenHeight(Context context) {
 97         WindowManager wm = (WindowManager) context
 98                 .getSystemService(Context.WINDOW_SERVICE);
 99         return wm.getDefaultDisplay().getHeight();
100     }
101 
102 }

 

屬性文件以下:ide

 

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MaxHeightView">
        <attr name="mhv_HeightRatio" format="reference|float" />
        <attr name="mhv_HeightDimen" format="reference|dimension" />
    </declare-styleable>

</resources>

 

使用方法:函數

在佈局中使用以下代碼:佈局

 

<cn.carbs.android.maxheightview.library.MaxHeightView
        android:id="@+id/maxview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:mhv_HeightRatio="0.7">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:gravity="center"
                android:text="MaxHeightView"
                android:textSize="20sp"/>

            <ScrollView
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <Button
                        android:layout_width="match_parent"
                        android:layout_height="60dp"
                        android:text="button0"/>

                    <Button
                        android:layout_width="match_parent"
                        android:layout_height="60dp"
                        android:text="button1"/>
                     ..........
      
                </LinearLayout>
            </ScrollView>
        </LinearLayout>
    </cn.carbs.android.maxheightview.library.MaxHeightView>

 

實現原理:spa

1.在構造方法中獲取最大高度或者最大高度的比例;code

2.在onMeasure()中經過獲取heightMeasureSpec的size判斷是否大於限定最大高度,若是大於,則將size設置爲限定最大高度,並從新生成heightMeasureSpec,並調用super.onMeasure(widthMeasureSpec, maxHeightMeasureSpec);以完成onMeasure對控件大小的設定

注意事項:

此自定義view繼承自FrameLayout,使用時最好嵌套一個ScrollView,以提升用戶體驗。

此view不完善的地方有,暫時不支持經過代碼生成MaxHeightView,不過能夠經過修改只有一個構造方法的public MaxHeightView(Context context)添加對應的mMaxHeight或者Ratio來限制大小。

代碼項目地址:

https://github.com/Carbs0126/MaxHeightView

歡迎指正。

相關文章
相關標籤/搜索