Android XML灵活布局之 EditText实现自适应高度同时限制最小和最大高度

本文已发到我的小号:https://juejin.im/post/5d033d145188256cd366d475

Android中使用XML布局应该是所有安卓开发者最熟悉的操作了,各种布局的特性想必大家也都了如指掌。但是,真正利用好各个布局以达到性能最优,或者配合实现一些单个布局无法实现的特性,在笔者看来是一个非常值得花心思去研究的问题。本文提供的解题思路并不复杂,如果你有其他方案(只通过xml实现),欢迎在评论中留言。

效果展示

不多废话,直接一个图看下要达到的效果⬇️

Jun-06-2019 19-34-17

在这个布局中,EditText实现了高度自适配,但限制于一屏内,文字超过一屏时则在EditText控件内进行滑动。充分利用了EditText的特性,避免了ScrollView的使用。

实现思路

为了实现图中的效果,分析可知最关键的点有三个:

  • 有最低高度。这个最简单,用EditText自带的minLines就可以达成效果

  • 高度要设为 android:layout_height="wrap_content"

  • EditText所占的空间只有一屏内的空白区域,并且不能超出此区域

于是我开始了不断尝试:

简单的LinearLayoutFrameLayout都会出现当文字超出一屏高度时,直接就往屏幕外部继续延长了。因为没办法将其限制在某个区域里,如果用LinearLayout的权重效果,那等于是直接占满空白区域了,明显也不是我们想要的。

那么需要一个可以限制其所在范围的布局,是不是一下就想到了用的最多也最方便的ConstrainLayout。可惜ConstrainLayout也不行,哪怕限制了底边相关联,但如果不设置高度为0dp,wrap_content的情况仍然会超出屏幕,而高度设为0时等于直接占满了。

同样还有使用Chains链,不仅位置无法固定,而且也解决不了高度越出的问题。最后我甚至还尝试了使用两个EditText,同时输入同样的文字,一个隐藏掉只用来确定高度,另一个按它的高度进行适配。结果当然也失败了,至少只用ConstrainLayout我是没有达成效果。

解决方案

在多次失败后,我一度以为是不是无法实现这样的效果了,要么妥协将EditText设为固定高度,或者使用ScrollView来配合,或者通过代码动态获取文字高度来设置控件高度。

但总不能那么轻易妥协,然后我想起了RelativeLayout,这个自从有了ConstrainLayout之后就已经被冷落了的布局。本来我以为后者是前者的"plus版",大哥都做不到的,小弟怎么能做到呢?

结果我还真被打脸了,测试后发现,EditTextRelativeLayout布局内,高度设为wrap_content时,既可以自适应高度,而且控件高度会被直接限制在根布局RelativeLayout内,也就是不会越出屏幕!

这下就真的能实现了,下面直接贴上代码:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white_fff"
    android:fitsSystemWindows="true"
    android:focusable="true"
    android:focusableInTouchMode="true">

    <com.widget.TitleBar
        android:id="@+id/titlebar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_42"
        app:leftText="返回"
        app:leftTextDrawableLeft="@mipmap/top_return" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="@dimen/dp_42">

        <EditText
            android:id="@+id/et_notice"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="24dp"
            android:layout_marginTop="14dp"
            android:layout_marginEnd="24dp"
            android:layout_marginBottom="@dimen/dp_62"
            android:background="@drawable/guild_rect_solid_f2f2f2_radius_3"
            android:gravity="start"
            android:hint="请输入公会公告"
            android:includeFontPadding="false"
            android:lineSpacingMultiplier="1.2"
            android:maxLength="1000"
            android:minLines="8"
            android:paddingStart="14dp"
            android:paddingTop="12dp"
            android:paddingEnd="14dp"
            android:paddingBottom="12dp"
            android:textAppearance="@style/guild_TextAppearance.262122_14"/>

        <TextView
            android:id="@+id/tv_word_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@+id/et_notice"
            android:layout_alignTop="@+id/tv_push"
            android:layout_alignBottom="@+id/tv_push"
            android:gravity="center"
            android:includeFontPadding="false"
            android:text="@string/guild_notice_tip"
            android:textColor="@color/grey_999"
            android:textSize="11sp" />

        <TextView
            android:id="@+id/tv_push"
            android:layout_width="wrap_content"
            android:layout_height="22dp"
            android:layout_alignEnd="@+id/et_notice"
            android:layout_alignBottom="@+id/et_notice"
            android:layout_marginTop="@dimen/dp_14"
            android:layout_marginBottom="-36dp"
            android:background="@drawable/guild_rect_solid_f81a1a_radius_11"
            android:gravity="center"
            android:includeFontPadding="false"
            android:paddingStart="9dp"
            android:paddingEnd="9dp"
            android:text="发布"
            android:textColor="@color/white_fff"
            android:textSize="12sp" />

    </RelativeLayout>
</FrameLayout>

最后

一番实验下来我发现虽然ConstrainLayoutRelativeLayout的很多api效果是差不多的,但实际上确实在一些临界情况上还是有不一样的表现。

比如RelativeLayout的layout_alignBottom="@+id/et_notice"layout_alignParentBottom="true" 的效果就是"底部对齐于其他控件的底部"和"底部对齐于根布局View的底部"。在ConstrainLayout中对应layout_constraintBottom_toBottomOf="@+id/et_notice"layout_constraintBottom_toBottomOf="parent"

虽然好像效果一样,不过ConstrainLayout中的margin是无法设置负值的,而其他布局可以,这一点是我觉得是ConstrainLayout不太灵活的一点,虽然需要设负值的情况很少见。

以上就是我在项目中自己发现的比较有意思的地方,虽然简单,但如果能帮助到别人就挺好的啦。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容