android:maxLines和android:ellipsize同时使用导致显示异常

Android开发必看:告别singleLine,用maxLines和textMultiLine的正确姿势 本文深入探讨了Android开发中弃用singleLine属性后,如何正确使用maxLines和textMultiLine进行替代。文章详细分析了新旧方案的设计差异,提供了从TextView静态文本限制到EditText多行输入控制的完整迁移策略、实战代码示例及常见陷阱的解决方案,帮助开发者实现平滑过渡并优化文本显示效果。 阅读详情

今天偶然发现android:maxLines和android:ellipsize这两个属性同时使用在某些设备上时不能正常工作,网上搜索了大半天最后终于还是在Stack-Overflow这个神奇的网上找到了一个满意的答案,原文地址如下:

http://stackoverflow.com/questions/2160619/android-ellipsize-multiline-textview


用法是将需要用到的TextView换成下面的EllipsizingTextView,然后在Java代码中使用setMaxLines(int maxLines)方法,直接传入一个所需要的最大行数即可,不需要再指定android:ellipsize参数或着使用setEllipsize这个方法(该方法在此类中被重写成了一个空方法,即不推荐使用的)


用这个方法基本上能在所有的设备上正常工作


需要注意的是,某情况使用如下的这三个属性可能也能实现

android:maxLines="4" 
android:ellipsize="marquee" 
android:singleLine="false" 

但是这种方法只能在部分设备上正常显示,并不能保证所有设备都正常(本人亲测过),所以最好还是用下面的EllipsizingTextView来实现


另外这个类还提供了一个监听器EllipsizeListener,这个监听器原文作者说的是开始在Ellipsize(这个单词不知道怎么读,网上也查不到,估计是Google自创的)的时候调用的,大概意思应该就是说在开始省略(也就是开始 ”...“ )的时候调用,这个暂时还没有试过,等以后需要的时候再去试一试


EllipsizingTextView.java

import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.widget.TextView;

public class EllipsizingTextView extends TextView {
    private static final String ELLIPSIS = "...";

    public interface EllipsizeListener {
        void ellipsizeStateChanged(boolean ellipsized);
    }

    private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>();
    private boolean isEllipsized;
    private boolean isStale;
    private boolean programmaticChange;
    private String fullText;
    private int maxLines = -1;
    private float lineSpacingMultiplier = 1.0f;
    private float lineAdditionalVerticalPadding = 0.0f;

    public EllipsizingTextView(Context context) {
        super(context);
    }

    public EllipsizingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void addEllipsizeListener(EllipsizeListener listener) {
        if (listener == null) {
            throw new NullPointerException();
        }
        ellipsizeListeners.add(listener);
    }

    public void removeEllipsizeListener(EllipsizeListener listener) {
        ellipsizeListeners.remove(listener);
    }

    public boolean isEllipsized() {
        return isEllipsized;
    }

    @Override
    public void setMaxLines(int maxLines) {
        super.setMaxLines(maxLines);
        this.maxLines = maxLines;
        isStale = true;
    }

    public int getMaxLines() {
        return maxLines;
    }

    @Override
    public void setLineSpacing(float add, float mult) {
        this.lineAdditionalVerticalPadding = add;
        this.lineSpacingMultiplier = mult;
        super.setLineSpacing(add, mult);
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int before, int after) {
        super.onTextChanged(text, start, before, after);
        if (!programmaticChange) {
            fullText = text.toString();
            isStale = true;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isStale) {
            super.setEllipsize(null);
            resetText();
        }
        super.onDraw(canvas);
    }

    private void resetText() {
        int maxLines = getMaxLines();
        String workingText = fullText;
        boolean ellipsized = false;
        if (maxLines != -1) {
            Layout layout = createWorkingLayout(workingText);
            if (layout.getLineCount() > maxLines) {
                workingText = fullText.substring(0, layout.getLineEnd(maxLines - 1)).trim();
                while (createWorkingLayout(workingText + ELLIPSIS).getLineCount() > maxLines) {
                    int lastSpace = workingText.lastIndexOf(' ');
                    if (lastSpace == -1) {
                        break;
                    }
                    workingText = workingText.substring(0, lastSpace);
                }
                workingText = workingText + ELLIPSIS;
                ellipsized = true;
            }
        }
        if (!workingText.equals(getText())) {
            programmaticChange = true;
            try {
                setText(workingText);
            } finally {
                programmaticChange = false;
            }
        }
        isStale = false;
        if (ellipsized != isEllipsized) {
            isEllipsized = ellipsized;
            for (EllipsizeListener listener : ellipsizeListeners) {
                listener.ellipsizeStateChanged(ellipsized);
            }
        }
    }

    private Layout createWorkingLayout(String workingText) {
        return new StaticLayout(workingText, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(),
                Alignment.ALIGN_NORMAL, lineSpacingMultiplier, lineAdditionalVerticalPadding, false);
    }

    @Override
    public void setEllipsize(TruncateAt where) {
        // Ellipsize settings are not respected
    }
}


Android TextView深度解析:从基础设置到高级适配与性能优化 在Android应用开发中,UI组件的正确使用是构建良好用户体验的基础。TextView作为最核心的文本显示控件,其内容、字体大小、颜色和背景的设置看似简单,实则涉及移动端开发的多个关键技术领域。理解其工作原理,需要掌握Android资源系统、屏幕适配机制和渲染性能优化等核心概念。通过资源化管理和主题化设计,开发者可以实现文本的国际化支持、深色主题适配以及动态样式切换,这对提升应用的可维护性和用户体验至关重要。在实际工程实践中,合理运用**sp与dp单位**进行字体适配,以及通过**ColorStateLi 阅读详情

相关推荐

Android TabLayout+ViewPager黄金组合实战指南

TabLayout和ViewPager是Android原生分页导航的核心组件,基于PagerAdapter实现Fragment页面容器与顶部标签栏的双向协同。其原理在于TabLayout负责UI渲染与用户交互,ViewPager承担页面调度与生命周期管理,二者通过setupWithViewPager建立松耦合绑定。该方案具备零第三方依赖、全版本兼容、调试友好等技术价值,广泛应用于电商详情页、教育App模块切换、政务平台多栏目等场景。相比ViewPager2需自行实现Tab逻辑,或BottomNavigati

dianjiaxian1205的博客 338

android:maxLines和android:ellipsize

android:maxLines和android:ellipsize同时使用的时候没有显示省略号,最后加上singleLine为false才显示出来。如下:android:maxLines="4" android:ellipsize="end" android:singleLine="false"只有end管用,其他的还是不能显示,有待研究。其中有一个作者提出了一下方法,作为参考:

lixue9185的博客 660

antdv-<a-form>的使用

是 Ant Design Vue 中用于创建表单的组件,提供了一种结构化的方式来收集用户输入。它支持多种布局、验证、数据绑定等功能,非常适合用于处理用户输入和提交数据。

2302_81312344的博客 2619

Android —— TextView中的MaxLines和ellipsize属性的冲突

最近发现在使用TextView时,有几个属性,使用出现冲突会导致行的错位: maxLines : ellipsize lineSpacingExtra 行间距 singleLine (可以与ellipze进行搭配使用) 1.maxLines 与ellipsize 搭配使用: 导致ellipsize失效。 解决: 1)如果maxLines=”1”,可以用singgeLine来代替,否则即使一行,

womengmengyan的博客 8387

Zynq裸机调试RTL8211FS网卡踩坑记:从ping不通到完美兼容的完整代码修改

本文详细记录了在Zynq平台上使用Xilinx SDK(XSDK)调试RTL8211FS网卡的完整过程,从最初的ping不通问题到最终实现完美兼容的解决方案。通过分析PHY芯片的寄存器配置差异,提供了关键代码修改和调试技巧,帮助开发者快速解决类似问题。

weixin_42550597的博客 421

别光看Demo了!用UE5 Lyra框架快速搭建你的多人对战游戏原型(含完整配置流程)

本文详细介绍了如何利用UE5 Lyra框架快速搭建多人对战游戏原型,包含完整的配置流程和实战案例。Lyra作为可直接二次开发的游戏模板,内置了GAS技能系统、Enhanced Input输入控制等核心功能,大幅缩短开发周期。通过替换角色模型、调整武器数值和配置新地图规则,开发者可在48小时内完成科幻团队竞技游戏原型的搭建。

weixin_28717411的博客 457

关于TextView的maxLines和ellipsize属性显示不正确情况之一的解决

前言:关于TextView的maxLines和ellipsize属性显示不正确网上有好几种情况,我这里只针对自己遇到的一种情况讨论。 下面主要说以下自己的问题即解决: 图片效果: 布局代码: &lt;TextView android:id="@+id/tv_product_intro_default" s...

零落凉辰@的专栏 2083

关于mos管的压降问题(项目遇到问题总结)

在研发过程中没有出现问题的板子,到了小批时竟出现雷达一直在触发???找了大几天,没有头绪。心中疑惑颇多,加上老板催促,自考等原因,真是压力山大。4月份自考,只有差不多一个月时间了吧,没有什么大的收获,反而在查找硬件问题的过程中,发现了一个自己忽视的一个问题,就是关于Mos管的压降问题。 备考的过程崎岖不平,工作又问题多多,孰轻孰重,如何取舍?从心理来说,不想取舍什么,只是有所得就可以,过不了就过不了呗,已经毕业十五年了,没这个本科文凭不也过来了吗?只是代表了自己在这一段时间的思考,自己兴趣吧,没什么大不了

guangod的博客 2万+

android maxLines ellipsize 配合使用失效,解决办法

首先,自定义一个TextView  package com.hx.readeralliance.customView; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Canvas; import android.text.La

struggling的专栏 7136

银河麒麟V10开机卡Logo?别慌,手把手教你进单用户模式修复(附详细命令)

本文详细解析银河麒麟V10操作系统启动时卡Logo的故障原因,并提供进入单用户模式的完整解决方案。通过GRUB引导菜单修改启动参数,执行文件系统检查、图形服务修复等关键命令,帮助用户快速恢复系统正常运行,适用于运维人员和普通用户应对紧急启动问题。

weixin_30522183的博客 392

PyTorch实战(26)——PyTorch分布式训练

在本节中,我们将探讨如何通过跨机器和机器内多进程的分布式训练来加速模型训练过程。我们将系统学习 PyTorch 提供的三大分布式训练 API——torch.distributed、torch.multiprocessing 以及 torch.utils.data.distributed.DistributedSampler,使用这些 API 能够极大的简化分布式训练,介绍如何使用 PyTorch 的分布式训练工具,在 CPU 和 GPU 上加速训练。

盼小辉丶的博客 3842

[bug]android:maxLines 和 android:ellipsize不能同时使用

今天偶然发现android:maxLines 和 android:ellipsize不能同时使用,同时使用的话会导致显示异常 总之不是你期待的结果 详情可以参考下面Google的buglist上的两个bug http://code.google.com/p/android/issues/detail?id=10554 http://code.google.com/p/android/i

Android Archive 707

Python与网络爬虫案例:电影评论抓取

接下来,我们就可以通过分析该页面中的HTML代码,来确定需要抓取的内容。在这段代码中,我们首先对每个评论div元素进行for循环,然后通过find方法获取class为'title'、'text'、'rating-other-user-rating'的元素,并将结果分别赋值给title、content和rating变量。在这段代码中,我们首先定义了目标网站的URL和headers信息,然后通过requests.get方法向目标网站发送了一个GET请求,并将返回的响应赋值给了response变量。

吃不胖. 1263

Android Studio中TextView的ellipsize配合maxLines显示坑点

在android studio中 maxLines为2,ellipsize为end的情况下,Preview窗口预览,并不是我们想要的。如图: 实际上,这是个坑。在真机跑起来,就正常了,不需做任何操作。 实际真机跑起来:

sm_xy的博客 2023

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Android TextView关于android:ellipsize=end的一个bug

疑惑今天在开发过程中遇到一个神奇的bug:需求很明确,TextView配置了关键的以下两行属性: <!--内容最大为2行,若内容过多,以...结尾--> <!--android:ellipsize="end"--> <!--android:maxLines="2"--> <TextView android:id="@+id/tv_content" android:lay

却把清梅嗅的博客 9554

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

android textview截断,Android Textview文字在底部被截断

所以我有2个文本视图,一个在另一个之上,但是当填充第二个文本视图时,剪切在底部被截断.标题为header_subtitle的textview存在问题很明显我错过了一些明显的东西,但不知道是什么.[问题]1这是代码:android:layout_width="match_parent"android:layout_height="match_parent">layout="@layout/se...

weixin_35615010的博客 1362

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android TextView深度解析:从核心属性到富文本与性能优化实战

在Android应用开发中,UI组件是构建用户界面的基础单元,其性能与灵活性直接影响用户体验。TextView作为最核心的文本显示组件,其设计原理涉及Android的测量、布局、绘制体系。深入理解TextView的运作机制,不仅能实现复杂的文本渲染需求,如富文本、图文混排,还能显著优化应用性能,减少不必要的布局计算与过度绘制。掌握其核心属性组合、Spannable富文本处理技术,以及在不同布局容器中的适配技巧,对于开发高效、精致的界面至关重要。本文聚焦TextView的实战应用,涵盖属性解析、动态文本处理、

weixin_29168675的博客 234

popwindow.show() ArrayIndexOutOfBoundsException

ListPopupWindow.show() 报了ArrayIndexOutOfBoundsException定位好久也没找到哪里的问题,换了好几种方法比如PopWindow+ListView/RecyclerView,都无作用。。 查看日志发现第一行显示这个 Error android.text.StaticLayout.calculateEllipsis 猜想是布局的问题,查看布局发现没

黄春的博客 390

Android布局设计全解析:从LinearLayout到ConstraintLayout实战指南

在移动应用开发中,用户界面布局是连接功能逻辑与用户体验的关键桥梁。其核心原理是通过视图容器(ViewGroup)构建树形结构,管理子视图的排列与定位。掌握布局技术不仅能提升应用视觉一致性,更能优化渲染性能,减少过度绘制。在实际工程实践中,开发者需要根据界面复杂度在传统布局(如LinearLayout、RelativeLayout)与现代布局(如ConstraintLayout)间做出合理选型。特别是ConstraintLayout,通过约束、链条等机制实现了扁平化布局,已成为复杂界面开发的首选方案。本文聚焦

weixin_30808693的博客 647

Android屏幕适配实战:ConstraintLayout解决多控件被挤出屏幕问题

在Android应用开发中,屏幕适配是构建高质量用户界面的核心挑战之一。传统布局方式如LinearLayout和RelativeLayout采用静态思维,依赖固定尺寸和复杂嵌套,难以应对不同屏幕尺寸和动态内容变化,常导致控件重叠或被挤出屏幕。ConstraintLayout(约束布局)通过声明式的关系约束机制,从根本上改变了这一局面。其核心原理是让控件通过建立与父容器、兄弟控件之间的约束关系来动态定位,结合偏斜(Bias)和链条(Chains)等特性,能够实现灵活的空间分配与自适应排列。这种技术方案显著提升

weixin_33816946的博客 383

Android卡片列表实战:RecyclerView+CardView性能优化与兼容性指南

RecyclerView是Android中实现高效列表展示的核心组件,其核心价值在于视图复用机制与解耦的布局管理能力;CardView则并非简单美化控件,而是Material Design物理分层理念的可编程实现,通过cardElevation和cardCornerRadius模拟纸张Z轴高度与边缘弯曲。二者协同的关键技术价值在于兼顾UI一致性与运行时性能,尤其在中低端设备上需规避阴影渲染、动态文本高度、ViewHolder状态残留等典型陷阱。典型应用场景包括电商商品列表、新闻信息流、设置项面板等纯展示型界

weixin_30897233的博客 420

Android屏幕适配全攻略:从dp到折叠屏

屏幕适配是移动开发中的基础技术挑战,其核心在于解决不同设备尺寸和像素密度的显示一致性。通过密度无关像素(dp)和缩放像素(sp)的标准化单位,开发者可以构建与设备无关的UI布局。现代Android开发中,ConstraintLayout通过百分比约束和屏障机制大幅提升了布局灵活性,而今日头条适配方案则通过动态计算density值实现全局适配。随着折叠屏设备的普及,开发者需要处理屏幕尺寸动态变化和多窗口模式等新场景。合理的资源文件管理和内存优化策略能有效控制APK体积,结合自动化测试可确保多设备兼容性。这些适

weixin_34216107的博客 306

Android布局开发全解析:从LinearLayout到ConstraintLayout的实战与优化

在Android应用开发中,用户界面(UI)的构建是基础且核心的环节,其关键在于理解布局(Layout)系统的工作原理。布局作为视图的容器和排列规则,通过测量(Measure)、布局(Layout)、绘制(Draw)流程,将视图树渲染到屏幕上,直接影响应用的性能与用户体验。掌握高效的布局技术,能够解决多屏幕适配、渲染性能优化等工程难题,对于构建流畅、稳定的应用至关重要。本文聚焦于Android开发中的布局管理器,深入剖析LinearLayout、RelativeLayout与现代主力ConstraintLa

congdi7904的博客 542
上一篇: AndroidPN测试(Android Push Notification)
下一篇: 各个版本的Xcode/IOS SDK官网下载
Chuekup
博客等级 码龄15年 17粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值