SpannableStringBuilder导致ellipsize失效(两者冲突)
来源:互联网 发布:win7新增打印机usb端口 编辑:程序博客网 时间:2024/06/16 08:48
这是一个自定义的控件,解决SpannableStringBuilder与ellipsize属性冲突的BUG,适用于ListView等有复用的列表里面,效果图在最底部。
package com.laka.jiawawa.ui.widget;import android.content.Context;import android.graphics.Canvas;import android.support.v7.widget.AppCompatTextView;import android.text.Spannable;import android.text.SpannableStringBuilder;import android.text.style.AbsoluteSizeSpan;import android.text.style.ForegroundColorSpan;import android.util.AttributeSet;import com.laka.jiawawa.R;import com.laka.jiawawa.util.Log;import com.laka.jiawawa.util.ResourceHelper;import com.laka.jiawawa.util.Utils;import java.util.HashMap;/** * @Author Lyf * @CreateTime 2017/12/12 * @Description **/public class SpannableTextView extends AppCompatTextView { private String mOriginalText; // 原文本 private final String mEllipsizedString = "..."; // 省略文本 private boolean isEllipsized = false; // 是否有添加过省略字符 private String mExchangeCoins = null; // 追加的部分文本(样式与主文本不同) // 设置部分字体的大小、颜色 private AbsoluteSizeSpan mAbsoluteSizeSpan; private ForegroundColorSpan mForegroundColorSpan; private SpannableStringBuilder mSpannableStringBuilder; // 保存已求得的最佳省略文本,Key是原文本,Value是最佳省略文本 private HashMap<String, String> mEllipsizedMap = new HashMap<>(); public SpannableTextView(Context context) { super(context); initView(); } public SpannableTextView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public SpannableTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private void initView(){ mSpannableStringBuilder = new SpannableStringBuilder(); mForegroundColorSpan = new ForegroundColorSpan(ResourceHelper.getColor(R.color.colorFFC038)); mAbsoluteSizeSpan = new AbsoluteSizeSpan((int) (11 * getContext().getResources().getDisplayMetrics().density + 0.5f)); } /** * @param exchangeCoins 追加的部分文本(样式与主文本不同) */ public void setExchangeCoins(String exchangeCoins) { // list 复用item时,需要重置状态 isEllipsized = false; if (Utils.isNotEmpty(exchangeCoins)) { this.mExchangeCoins = exchangeCoins; // 求得原文本 mOriginalText = getText() + mExchangeCoins; // 如果有最佳的省略文本,就直接设置. if (mEllipsizedMap.get(mOriginalText) != null) { setText(mEllipsizedMap.get(mOriginalText)); } else { setText(mOriginalText); } invalidate(); } } @Override protected void onDraw(Canvas canvas) { // 有设置追加文本的,才进行计算 if (Utils.isNotEmpty(mExchangeCoins)) { CharSequence charSequence = getText(); // 重置状态 mSpannableStringBuilder.clear(); // 追加部分文本的长度 int length = mExchangeCoins.length(); // 被省略的文本的长度 int ellipsisCount = getLayout().getEllipsisCount(getLineCount() - 1); // 如果省略的文本长度大于0并且当前原文本没有对应的最佳省略文本,则进行计算 if (ellipsisCount > 0 && mEllipsizedMap.get(mOriginalText) == null) { // 是否有添加过省略字符 if (isEllipsized) { //消除被省略掉的文本,并以mEllipsizedString显示 charSequence = deleteEllipsizeText(charSequence,ellipsisCount,length); } else { // 已添加省略字符 charSequence = setEllipsizedString(charSequence,length); } } else { // 设置文本 charSequence = (charSequence.subSequence(0, charSequence.length() - length)) + mExchangeCoins; // 保存最佳省略文本 mEllipsizedMap.put(mOriginalText,charSequence.toString()); } // 设置样式 setSpannable(charSequence,length); } super.onDraw(canvas); } /** * 消除被省略掉的文本,并以mEllipsizedString显示 */ private String deleteEllipsizeText(CharSequence charSequence , int ellipsisCount ,int length) { // 获取主标题(不包含追加文本) charSequence = charSequence.subSequence(0, charSequence.length() - length); //Log.log("削减前="+charSequence); // 循环,从省略字符左右不断削减字符,直到被省略的字符数为0. while (ellipsisCount > 0){ int midIndex = charSequence.toString().indexOf(mEllipsizedString); // 省略字符的左边 int startLength = charSequence.subSequence(0, midIndex).length(); // Log.log("省略符左边的文本="+charSequence.subSequence(0, midIndex)); // 省略字符的右边 int endLength = charSequence.subSequence(midIndex + 3, charSequence.length()).length(); // Log.log("省略符右边的文本="+charSequence.subSequence(midIndex + 3, charSequence.length())); // 省略字符的左边的文本大于右边的,则削减左边的文本 if (startLength >= endLength) { // Log.log("左边的文本大于右边"); charSequence = charSequence.subSequence(0, midIndex - 1).toString() + charSequence.subSequence(midIndex , charSequence.length()).toString(); } else { // Log.log("右边的文本大于左边"); // 省略字符的右边的文本大于左边的,则削减右边的文本 charSequence = charSequence.subSequence(0, midIndex + 3).toString() + charSequence.subSequence(midIndex + 4, charSequence.length()).toString(); } --ellipsisCount; // Log.log("削减后(循环中)="+charSequence); } //Log.log("削减后(循环已结束,最终结果)="+charSequence); // 削减完毕,将追加部分添加回来 return charSequence + mExchangeCoins; } /** * 已添加省略字符 */ private String setEllipsizedString(CharSequence charSequence , int length) { isEllipsized = true; // 求得主标题的长度(不包含追加文本) int middle = (charSequence.length() -length) / 2; // 去掉主标题中间四字个字符换成省略字符 String startTemp = charSequence.subSequence(0, middle - 2) + mEllipsizedString; return startTemp + charSequence.subSequence(middle + 2, charSequence.length()); } /** * 设置样式 * @param mExchangeCoinsLength 追加文本的长度 */ private void setSpannable(CharSequence charSequence ,int mExchangeCoinsLength) { // 设置文本 mSpannableStringBuilder.append(charSequence); int end = mSpannableStringBuilder.toString().trim().length(); int start = end - mExchangeCoinsLength; mSpannableStringBuilder.setSpan(mForegroundColorSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mSpannableStringBuilder.setSpan(mAbsoluteSizeSpan, start, end, Spannable. SPAN_EXCLUSIVE_EXCLUSIVE); setText(mSpannableStringBuilder); }}
阅读全文
0 0
- SpannableStringBuilder导致ellipsize失效(两者冲突)
- DevExpress与长连接冲突导致DevExpressAJax事件失效
- JS与DOCTYPE冲突导致漂浮代码失效的解决方法
- logback冲突导致日志级别失效的解决办法
- android maxLines ellipsize 配合使用失效,解决办法
- android:maxLines与android:ellipsize冲突
- Log4j和logback冲突,导致log4j配置失效控制台一直打印DEBUG级别的日志
- SpannableStringBuilder
- SpannableStringBuilder
- SpannableStringBuilder
- spannableStringBuilder
- SpannableStringBuilder
- 分析 TextView 应用 Spannable 风格后 ellipsize 属性失效
- android TextView 使用SpannableString数据源时,TextView的ellipsize失效
- 【同一个Server Weblogic两个Domain CookieName冲突导致session失效问题】【关于WebLogic的Session丢失的问题】
- Ubuntu安装冲突软件导致窗口顶部窗体消失,Unity启动器消失,桌面顶部任务栏消失,快捷键失效解决方法
- 解决TextView中MaxLines与ellipsize=end冲突问题
- 解决TextView中MaxLines与ellipsize=end冲突问题
- 客户端接收服务端消息推送sockjs-client的使用
- 调戏木马病毒的正确姿势-基础篇
- 点击页面上的一个按钮时,如何触发controller中的方法
- date对象常用方法
- C#的银行家算法的实现
- SpannableStringBuilder导致ellipsize失效(两者冲突)
- 移动端根据屏幕大小自动设置body字体大小
- 动态规划之零件加工
- 小学生开始学Python,还有什么能够阻挡我对Python的向往?
- 舒服的判断当前应用是否处于前台
- Golang从入门到精通(十四):Golang结构体
- 数组 链表 哈希表
- 数据结构实验之查找三:树的种类统计
- 【剧透】2017云栖大会·北京峰会——企业云上业务优化专场