• [原创]android自定义控件的最大高度MaxHeightView


    代码地址:https://github.com/Carbs0126/MaxHeightView

    android中部分控件具有maxHeight功能,如button等,但是对于ViewGroup类的控件,没有此属性,当我们需要限制某些view的高度时,(比如限制屏幕下方对话框的最大高度)那么,就需要一种可以限制其子view最大高度的ViewGroup。如何为自定义ViewGroup添加一个最大高度的属性呢?其实很简单,主要就是使用onMeasure()函数,在函数中控制高度即可。

    先看下效果图:

    这是一个dialog,dialog中添加了共有20个button,如果不使用最大高度可控的viewgroup,则会充满整个屏幕。

    java代码实现如下:

      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 }

    属性文件如下:

    <?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>

    实现原理:

    1.在构造方法中获取最大高度或者最大高度的比例;

    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

    欢迎指正。

  • 相关阅读:
    模拟http请求 带 chunked解析办法一
    DLL入口函数
    修复吾爱OD数据窗口双击不出现偏移问题
    PE导入表分析
    持仓盈亏公式
    hadoop工作相关
    zookeeper常用命令
    git使用命令行上传文件
    redis中各种数据类型对应的jedis操作命令
    volatile关键字比较好的解释
  • 原文地址:https://www.cnblogs.com/carbs/p/5142758.html
Copyright © 2020-2023  润新知