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

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

先看下效果图:

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

java代码实现如下:

 package cn.carbs.android.maxheightview.library;

 /**
* Created by carbs on 2016/5/12.
*/
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.WindowManager;
import android.widget.FrameLayout; /**
* 先判断是否设定了mMaxHeight,如果设定了mMaxHeight,则直接使用mMaxHeight的值,
* 如果没有设定mMaxHeight,则判断是否设定了mMaxRatio,如果设定了mMaxRatio的值 则使用此值与屏幕高度的乘积作为最高高度
*
* @author Carbs
*/
public class MaxHeightView extends FrameLayout { private static final float DEFAULT_MAX_RATIO = 0.6f;
private static final float DEFAULT_MAX_HEIGHT = 0f; private float mMaxRatio = DEFAULT_MAX_RATIO;// 优先级高
private float mMaxHeight = DEFAULT_MAX_HEIGHT;// 优先级低 public MaxHeightView(Context context) {
super(context);
init();
} public MaxHeightView(Context context, AttributeSet attrs) {
super(context, attrs);
initAttrs(context, attrs);
init();
} public MaxHeightView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initAttrs(context, attrs);
init();
} private void initAttrs(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.MaxHeightView); final int count = a.getIndexCount();
for (int i = 0; i < count; ++i) {
int attr = a.getIndex(i);
if(attr == R.styleable.MaxHeightView_mhv_HeightRatio){
mMaxRatio = a.getFloat(attr, DEFAULT_MAX_RATIO);
}else if(attr == R.styleable.MaxHeightView_mhv_HeightDimen){
mMaxHeight = a.getDimension(attr, DEFAULT_MAX_HEIGHT);
}
}
a.recycle();
} private void init(){
if (mMaxHeight <= 0) {
mMaxHeight = mMaxRatio * (float) getScreenHeight(getContext());
} else {
mMaxHeight = Math.min(mMaxHeight, mMaxRatio * (float) getScreenHeight(getContext()));
}
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (heightMode == MeasureSpec.EXACTLY) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
} if (heightMode == MeasureSpec.UNSPECIFIED) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
if (heightMode == MeasureSpec.AT_MOST) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,
heightMode);
super.onMeasure(widthMeasureSpec, maxHeightMeasureSpec);
} /**
* 获取屏幕高度
*
* @param context
*/
private int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
return wm.getDefaultDisplay().getHeight();
} }

属性文件如下:

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

欢迎指正。

[原创]android自定义控件的最大高度MaxHeightView的更多相关文章

  1. Android自定义控件之自定义ViewGroup实现标签云

    前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言 ...

  2. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  3. Android自定义控件之基本原理

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自 ...

  4. android自定义控件——以滑动开关为例

    0.引言 (1)Android从4.0开始提供了switch的滑动开关效果组件,但是之前版本却没有 (2)很多时候我们写程序,都希望把有用的通用的通用的东西封装起来,以便以后重用. 本文根据组件开发思 ...

  5. Android自定义控件之基本原理(一)

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自 ...

  6. Android自定义控件之自定义组合控件(三)

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  7. Android自定义控件实现带有清除按钮的EditText

    首先声明我也是参考了别人的思路,只是稍微做了下修改,增加显示密码与隐藏密码,没有输入字符串时让EditText进行抖动,废话少说这里附上效果图 效果很赞有木有 那么怎么实现这种效果呢?那就跟着我一起来 ...

  8. [转]Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)

    最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习.发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧. 一.控件介绍: 进度条在App中非 ...

  9. Android自定义控件之自定义属性

    前言: 上篇介绍了自定义控件的基本要求以及绘制的基本原理,本篇文章主要介绍如何给自定义控件自定义一些属性.本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解.有关原理知识请参考Android自定义控 ...

随机推荐

  1. UIScrollView滚动视图

    一.基本知识 1.初始化 UIScrollView #import "ViewController.h" #define WIDTH[[UIScreen mainScreen]bo ...

  2. Google被墙 Android开发工具下载地址

    Android开发环境的官网下载地址 可以直接下载 (1)Adt Bundle Platform Package Size MD5 Checksum Windows 32-bit adt-bundle ...

  3. Windows7上搭建Cocos2d-x 3.1.1开发环境

    前言 现在,越来越多的公司采用Cocos2d-x 3.0来开发游戏了,但是现在这样的文章并不多,所以打算写一系列来帮助初学者快速掌握Cocos2d-x 3.0.首先就从开发环境的大家说起吧. 开发工具 ...

  4. 移植到Windows CE 的经验

    Windows CE 是微软早期推出的嵌入式设备和移动设备的开发运行平台,虽然目前移动端几乎都是android和ios的天下,但是,在嵌入式设备领域,Windows CE仍然占有一块地盘.很多用户希望 ...

  5. 设计模式之美:Structural Patterns(结构型模式)

    结构型模式涉及到如何组合类和对象以获得更大的结构. 结构型类模式采用继承机制来组合接口实现. 结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法. 因为 ...

  6. Linux:目录&文件基本操作

    - 表示上一次所在目录,- 通常表示当前用户的"home"目录.使用 pwd 命令可以获取当前所在路径(绝对路径). 新建文件:touch test创建目录:mkdir -p fa ...

  7. ActiveMQ第三弹:在Spring中使用内置的Message Broker

    在上个例子中我们演示了如何使用Spring JMS来向ActiveMQ发送消息和接收消息.但是这个例子需要先从控制台使用ActiveMQ提供的命令行功能启动一个Message Broker,然后才能运 ...

  8. 由Memcached使用不当而引发性能问题的两个经验总结

    在这个cache everywhere的时代,在这个人人都会说分布式缓存的时代,Memcached几乎已成为网站开发中的标配. 作为一名普通的coder,我们在编写缓存代码的时候,很多情况下可能都只是 ...

  9. 再谈:jquery编写插件的方法

    版权声明:作者原创,转载请注明出处! 编写插件的两种方式: 1.类级别开发插件(1%) 2.对象级别开发(99%) 类级别的静态开发就是给jquery添加静态方法,三种方式 1.添加新的全局函数 2. ...

  10. struts2学习笔记之一:基本简介

    Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个Servlet,在MVC设计模式中,Struts2作为控制器来建立模型与视图的数据交互(所有的访问都会被控制器操作控制)   ...