android自定义控件的最大高度MaxHeightView

android中部分控件具有maxHeight功能,如button,但是对于ViewGroup类的控件,没有此属性,那么,如何为ViewGroup添加一个最大高度的属性呢?其实很简单,主要就是使用onMeasure()函数,在函数中控制高度即可。

先看下效果图:

这是一个dialog,dialog中添加了共有17个button,如果不使用最大高度可控的view,则体验效果不好,可能会完全遮住后边的背景。

java代码实现如下:

  1 package cn.carbs.maxheightview;
  2
  3 import android.content.Context;
  4 import android.content.res.TypedArray;
  5 import android.util.AttributeSet;
  6 import android.util.Log;
  7 import android.view.View;
  8 import android.view.WindowManager;
  9 import android.widget.FrameLayout;
 10
 11 /**
 12  * 先判断是否设定了mMaxHeight,如果设定了mMaxHeight,则直接使用mMaxHeight的值,
 13  * 如果没有设定mMaxHeight,则判断是否设定了mMaxRatio,如果设定了mMaxRatio的值
 14  * 则使用此值与屏幕高度的乘积作为最高高度
 15  * @author Rick.Wang
 16  *
 17  */
 18 public class MaxHeightView extends FrameLayout{
 19
 20     private static final float DEFAULT_MAX_RATIO = 0.4f;
 21     private static final float DEFAULT_MAX_HEIGHT = -1f;
 22
 23     private Context mContext;
 24     private float mMaxHeight = DEFAULT_MAX_HEIGHT;//优先级高
 25     private float mMaxRatio = DEFAULT_MAX_RATIO;//优先级低
 26
 27     public MaxHeightView(Context context) {
 28         this(context, null);
 29     }
 30
 31     public MaxHeightView(Context context, AttributeSet attrs) {
 32         this(context, attrs, 0);
 33     }
 34
 35     public MaxHeightView(Context context, AttributeSet attrs, int defStyle) {
 36         super(context, attrs, defStyle);
 37         mContext = context;
 38
 39         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.maxHeightView);
 40
 41         final int count = a.getIndexCount();
 42         for (int i = 0; i < count; ++i) {
 43             int attr = a.getIndex(i);
 44             switch (attr) {
 45             case R.styleable.maxHeightView_maxHeightRatio:
 46                 mMaxRatio = a.getFloat(attr, DEFAULT_MAX_RATIO);
 47                 break;
 48             case R.styleable.maxHeightView_maxHeightDimen:
 49                 mMaxHeight = a.getDimension(attr, DEFAULT_MAX_HEIGHT);
 50                 break;
 51             }
 52         }
 53         a.recycle();
 54
 55         if(mMaxHeight < 0){
 56             mMaxHeight = mMaxRatio * (float)getScreenHeight(mContext);
 57         }
 58     }
 59
 60     @Override
 61     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 62
 63         int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
 64         int heightSize = View.MeasureSpec.getSize(heightMeasureSpec);
 65
 66         Log.d("wang", "onMeasure heightSize is " + heightSize + " | mMaxHeight is " + mMaxHeight);
 67
 68         if(heightMode == View.MeasureSpec.EXACTLY){
 69             Log.d("wang", "heightMode == View.MeasureSpec.EXACTLY");
 70             heightSize = heightSize <= mMaxHeight ? heightSize : (int)mMaxHeight;
 71         }
 72
 73         if(heightMode == View.MeasureSpec.UNSPECIFIED){
 74             Log.d("wang", "heightMode == View.MeasureSpec.UNSPECIFIED");
 75             heightSize = heightSize <= mMaxHeight ? heightSize : (int)mMaxHeight;
 76         }
 77         if(heightMode == View.MeasureSpec.AT_MOST){
 78             Log.d("wang", "heightMode == View.MeasureSpec.AT_MOST");
 79             heightSize = heightSize <= mMaxHeight ? heightSize : (int)mMaxHeight;
 80         }
 81
 82         int maxHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(heightSize, heightMode);
 83
 84         super.onMeasure(widthMeasureSpec, maxHeightMeasureSpec);
 85     }
 86
 87
 88     /**
 89      * 获取屏幕高度
 90      * @param context
 91      */
 92     public static int getScreenHeight(Context context){
 93         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
 94         return wm.getDefaultDisplay().getHeight();
 95     }
 96
 97     /**
 98      * 获取屏幕宽度
 99      * @param context
100      */
101     public static int getScreenWidth(Context context){
102         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
103         return wm.getDefaultDisplay().getWidth();
104     }
105
106     /**
107      * 获取屏幕大小
108      * @param context
109      * @param outDimension
110      */
111     public static void getScreenDimension(Context context, int[] outDimension){
112         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
113         outDimension[0] = wm.getDefaultDisplay().getWidth();
114         outDimension[1] = wm.getDefaultDisplay().getHeight();
115     }
116
117 }

属性文件如下:

attrs.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3
 4     <declare-styleable name="maxHeightView">
 5         <attr name="maxHeightRatio" format="reference|float" />
 6         <attr name="maxHeightDimen" format="reference|dimension" />
 7     </declare-styleable>
 8
 9
10 </resources>

使用方法:

在布局中使用如下代码:

 1 <cn.carbs.maxheightview.MaxHeightView
 2         android:id="@+id/maxview"
 3         android:layout_width="match_parent"
 4         android:layout_height="wrap_content"
 5         app:maxHeightRatio="0.7" >
 6
 7         <ScrollView
 8             android:layout_width="match_parent"
 9             android:layout_height="wrap_content" >
10
11             <LinearLayout
12                 android:layout_width="match_parent"
13                 android:layout_height="wrap_content"
14                 android:orientation="vertical" >
15
16                 <Button
17                     android:id="@+id/button0"
18                     android:layout_width="match_parent"
19                     android:layout_height="60dp"
20                     android:text="button0" />
21               ...............
22
23             </LinearLayout>
24         </ScrollView>
25     </cn.carbs.maxheightview.MaxHeightView>

要注意,此自定义view继承自FrameLayout,使用时最好嵌套一个ScrollView,以提高用户体验

时间: 2024-10-12 23:23:26

android自定义控件的最大高度MaxHeightView的相关文章

android 自定义控件---圆形方向盘

在做Android平台开发的时候,经常会遇到安卓原生控件无法满足需求的情况,安卓允许开发者去继承已经存在的控件或者实现你自己的控件. 先来看一下效果图 采用直接集成View类,重写onDrow方法绘制. 下面附上主要代码. 1 新建一个类CircleView 继承自View 1 package com.lennon.view; 2 3 import android.content.Context; 4 import android.graphics.Canvas; 5 import androi

Android自定义控件之自定义ViewGroup实现标签云(四)

前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言道:“好记性不如烂笔头,光说不练假把式!!!”,作为一名学渣就是因为没有遵循这句名言才沦落于此,所以要谨遵教诲,注重理论与实践相结合,今天通过自定义ViewGroup来实现一下项目中用到的标签云. 需求背景: 公司需要实现一个知识点的标签显示,每个标签的长度未知,如下图所示 基本绘制流程: 绘制原理

Android自定义控件---继承ProgressBar功能扩展

一.前言 前一段时间在做视频开发,由于本人刚接触视频开发这块,所以 领导没有对我提很高的要求,仅仅要求能够播放本地视频即可. 我想怎么简单怎么做.于是选择用Android VideoView控件来播放视频 (后面发现VideoView的灵活性实在太差,我不想吐槽). 最终的效果图: 视频全屏效果 这次的任务主要难度在于进度条这个控件.各位可以从上面的两张图中看到,进度条被分 为三段.每段表示一个视频,并且每个视频的长度不一,也就意味着每段视频进度条的前进速度是不相同的. 难点总结: 1.自定义控

Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一)

转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45027641 自定义view/viewgroup要重写的几个方法:onMeasure(),onLayout(),onDraw().(不熟悉的话可以查看专栏的前几篇文章:Android自定义控件系列二:自定义开关按钮(一)). 今天的任务就是详细研究一下protected void onMeasure(int widthMeasureSpec, int heightMeasureSpe

Android 自定义控件 优雅实现元素间的分割线 (支持3.0以下)

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42407923 ,本文出自:[张鸿洋的博客] 1.概述 话说,随着Android SDK版本的升级,很多控件增加了新的属性方便我们的使用,比如LinearLayout中多了:divider.showDividers等,用于为其内部元素添加分隔:但是呢,这样的属性在较低版本的SDK中不能被支持,那么,我们在开发过程中,可能会出现这样的需求:将这个新的特性想办法做到尽可能的向下兼容.

Android自定义控件背景及其Drawable以实现扁平化

扁平化? 人们都说扁平化是从IOS和WindowsPhone那边吹过来的邪风,但是不可否认:扁平化是我见过的最舒服.最自然的表现方式.从开发角度上来讲,扁平化的设计可以使得我们从许多屏幕适配和尺寸调节的工作中解放出来(虽然只是那么一点点),更加关注功能:而在在使用层面上,只要文化水平不是特别地低(没有恶意),拟物化的那点提示作用也不是那么明显,当然这里不是说拟物化不好,总之:相对于其他表现方式,扁平化碉堡了. 咱们也做一个扁平化 上面说了,扁平化的控件其实在开发中是非常容易的.这里让我们一起动手

Android自定义控件---“取消”视图

一.前言 好久没更新博客了,最近一直在忙,找实习,整理毕业资料,找房子等等.现在大部分基本忙完了,这几天在公司写的一些自定义控件,打算发出来与大家分享. 首先看看最终的效果图 这个自定义视图的应用场景,主要用于替代对话框左上角或者右上角的取消按钮.按照我以前的做法,都是设计师发给我一张图片,我自己创建一个ImageView,再把图片设置进去就结束了.如果有天产品经理看得不爽,想要圆形,或矩形,对角线想要XXX颜色.又得等设计师发图了(本人不太会PS啊).所以为了避免麻烦,打算自己写一个. 二.自

Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一),今天就来真正实践一下,让这两个方法大显神威来帮我们搞定图片的屏幕适配问题. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45038329,非允许请勿用于商业或盈利用途,违者必究. 使用ImageView会遇到

Android学习(十)—— Android自定义控件

Android自定义控件 安卓在使用中大多数使用已有的一些控件,用法比较简单,还有一部分是比较复杂的.用户自己想的控件,这些就需要进行自定义控件,今天就来简单说一下自定义控件. 1.绘制过程 创建一个类,继承View类 onMeasure()方法,测量计算视图的大小 onLayout()方法,设置视图在屏幕中显示的位置 onDraw()方法,绘制视图 以上就是自定义控件的绘制过程. 2.主要内容解释 measure操作 用于计算视图的大小,即视图的宽度和长度.在view中定义为final类型,要