TextView
TV内容过长,显示省略号
TextView中有个ellipsize属性,作用是当文字过长时,该控件该如何显示,解释如下:
android:ellipsize="start"
—–省略号显示在开头android:ellipsize="end"
——省略号显示在结尾android:ellipsize="middle"
—-省略号显示在中间android:ellipsize="marquee"
–以跑马灯的方式显示(动画横向移动)
以上需要搭配 android:maxLines="1"
属性才可生效(android:singleLine="true"
已经不推荐使用)
TV的省略号不起效
解析:设置了属性
1 | android:ellipsize="end" |
但在代码中使用了以下的代码,导致省略号不起效
1 | StringHelpUtils.setSpannableString(tv, color, name, matchStr); |
其中setSpannableString的代码是
1 | /** |
是因为textView.setMovementMethod
影响到的
解决:
方法一:使用
android:singleLine="true"
可以解决上述问题,但是这个属性不推荐了方法二:自己拼接
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46import android.text.TextUtils;
import android.view.ViewTreeObserver;
import android.widget.TextView;
public class OnGlobalLayoutListenerByEllipSize implements ViewTreeObserver.OnGlobalLayoutListener {
private TextView mTextView;
private int mMaxLines;
public OnGlobalLayoutListenerByEllipSize(TextView textView, int maxLines) {
if (maxLines <= 0) {
throw new IllegalArgumentException("maxLines不能小于等于0");
}
this.mTextView = textView;
this.mMaxLines = maxLines;
this.mTextView.setMaxLines(mMaxLines + 1);
this.mTextView.setSingleLine(false);
}
public void onGlobalLayout() {
if (mTextView.getLineCount() > mMaxLines) {
int line = mTextView.getLayout().getLineEnd(mMaxLines - 1);
//定义成CharSequence类型,是为了兼容emoji表情,如果是String类型会造成emoji无法显示
CharSequence truncate = "...";
CharSequence text = mTextView.getText();
try {
text = text.subSequence(0, line - 3);
} catch (Exception e) {
truncate = "";
text = mTextView.getText();
}
TextUtils.TruncateAt at = mTextView.getEllipsize();
if (at == TextUtils.TruncateAt.START) {
mTextView.setText(truncate);
mTextView.append(text);
} else if (at == TextUtils.TruncateAt.MIDDLE) {
mTextView.setText(text.subSequence(0, text.length() / 2));
mTextView.append(truncate);
mTextView.append(text.subSequence(text.length() / 2, text.length()));
} else {
mTextView.setText(text);
mTextView.append(truncate);
}
}
}
}调用:
tv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListenerByEllipSize(tv,1));
但此种做法会导致tv后面会多一些空白,使用控件位置检测看到有个空白的控件(未解决)
方法三:去掉
tv.setMovementMethod(LinkMovementMethod.getInstance());
(会导致span不能点击了),然后自己添加点击事件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44// textview点击监听
linkText.setOnTouchListener(new View.OnTouchListener() {
long startTime = 0;
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
startTime = System.currentTimeMillis();
}
TextView tv = (TextView) v;
CharSequence text = tv.getText();
if (text instanceof SpannableString) {
if (action == MotionEvent.ACTION_UP) {
// 避免长按和点击冲突,如果超过300毫秒,认为是在长按,不执行点击操作
if (System.currentTimeMillis() - startTime > 300) {
return false;
}
int x = (int) event.getX();
int y = (int) event.getY();
x -= tv.getTotalPaddingLeft();
y -= tv.getTotalPaddingTop();
x += tv.getScrollX();
y += tv.getScrollY();
Layout layout = tv.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = ((SpannableString) text).getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
return true;
}
}
}
return false;
}
});
TV部分关键字带下划线可点击的
1 | <declare-styleable name="AutoLinkStyleTextView"> |
使用
1 | <xx.AutoLinkStyleTextView |
1 | autoLinkStyleTextView.setOnClickCallBack(new AutoLinkStyleTextView.ClickCallBack() { |
TV部分文字响应点击事件
- 给TextView设置设置文字背景为透明色,不然会有点击选中效果
- SpannableString拼接字符串,给8到11的字符串用Clickable对象去处理
1).Clickable对象继承ClickableSpan 实现了onclick()跟updateDrawState()方法
2).onclick()处理点击事件,updateDrawState()中可以改变字体颜色,控件背景色
1 | public class MainActivity extends Activity { |
1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
TV部分文字响应点击事件(法2)
1 | import android.text.TextPaint; |
使用
1 | //感谢使用爱学拼音!使用前请仔细阅读《用户协议》和《隐私协议》了解您的合法权益。我们将严格遵守承诺,保护个人信息。 |
TV加中划线、下划线
加中划线
1 | tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);//设置中划线 |
加下划线(5种做法)
将要处理的文字写到一个资源文件,如string.xml(使用html用法格式化)
1
2
3
4<resources>
<string name="hello"><u>phone:0123456</u></string>
<string name="app_name">MyLink</string>
</resources>当文字中出现URL、E-mail、电话号码等的时候,可以将TextView的android:autoLink属性设置为相应的的值,如果是所有的类型都出来就是android:autoLink=”all”,当然也可以在java代码里 做,textView01.setAutoLinkMask(Linkify.ALL);
1
2
3
4
5
6<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:autoLink="all"
android:text="@string/link_text_auto" />用Html类的fromHtml()方法格式化要放到TextView里的文字 ,与第1种一样,只是是用代码动态设置
1
2TextView textView = (TextView)findViewById(R.id.tv_test);
textView.setText(Html.fromHtml("<u>"+"0123456"+"</u>"));设置TextView的Paint属性:tvTest.getPaint().setFlags(Paint. UNDERLINE_TEXT_FLAG ); //下划线
1
2tvTest.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG); //下划线
tvTest.getPaint().setAntiAlias(true);//抗锯齿用Spannable或实现它的类,如SpannableString来格式部分字符串。
1
2SpannableString content = new SpannableString(str);
content.setSpan(new UnderLineSpan, 0, str.length(), 0);另外附上一篇博客介绍:Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
取消设置的线
1 | tv.getPaint().setFlags(0); // 取消设置的的划线 |
自定义超链接样式
1 | TextView tv=new TextView(this); |
Tv跑马灯
有时文字过长,又只想单行显示来节省空间,走马灯式显示是个不错的选择。(饿了么顶部地址显示就是这种情况)
其实只要在布局文件的Textview
中添加属性android:ellipsize="marquee"
但是要在获得焦点的情况下该属性才会起作用。
那么怎么让控件一直获得焦点呢?
系统判断TextView
是否获得焦点是通过 isFocused()
这个方法的返回值来判断
这样的话就可以新创建一个类,继承Textveiw
,重写isFoused()
方法,让它返回true
就ko了。
文字左右滚动三个属性:
1 | android:singleLine="true" |
Tv动态添加drawableLeft
1 | Drawable drawable = mContext.getResources().getDrawable(R.drawable.icon_location_4); |
判断是否所有TextView都不为空
1 | package com.xm597.common.manager; |
调用:
1 | ArrayList<TextView> textViews = new ArrayList<>(); |
判断页面所有控件是否有为空的
注:
extraIds是表示不参与判断的控件的id,可以对这些id在页面中单独判断
底下的AllWidgetHasEmpty目前只添加了TextView的处理(EditText是继承于TextView),要对页面中其他种类的控件进行判空的话要在这个类中添加对应的类型以及它的判空逻辑。
1 | import android.text.TextUtils; |
使用:
先在基类Activity中写,方便它的子类直接使用
1 | //BaseActivity.java |
子类Activity中使用:
1 |
|
进一步封装
1 | import android.view.View; |
使用:
先在基类中写
1 | //BaseActivity.java中 |
在具体子类中使用
1 | //重写两个方法即可 |
标题右侧带个标签,标题长度是包裹内容且能换行(标签不能顶出屏幕)
方法一:
1 | <LinearLayout |
方法二:
另一个思路:
在代码中动态测量,动态设置左侧标题的宽度
1 | titleTv.setText(jobRow.getJname()); |
Tv英文的换行问题
思路:动态测量,手动切割字符串
设置可滚动
1 | <TextView |
设置scrollbars属性(有三个属性 horizontal、vertical、none)
系统默认scrolbar是渐隐效果,如果需要常显设置 android:fadeScrollbars=”false”
1 | class MainActivity : AppCompatActivity(){ |
调用 public final void setMovementMethod(MovementMethod movement){},设置 MovementMethod
显示html
1 | tv.setText(Html.fromHtml(htmlStr)); |
支持外链跳转
1 | <TextView |
添加 android:autoLink 属性
TextView相关问题
tv.setTextColor(color)
显示出来的颜色值不对
解决:tv.setTextColor(R.color.red);//不报错,但是显示效果不是红色
改成 tv.setTextColor(getResource().getColor(R.color.red));//即可
显示不出省略号…的问题
1 | <TextView |
解决:网上查tv有android:inputType="text"
属性要去掉。此处的问题是android:maxLength="10"
属性,改成android:maxEms="10"
即可
TextView跑马灯无效
1 | <TextView |
android:marqueeRepeatLimit=”marquee_forever”重复次数
默认是需要获取到焦点才能滚动,所以多个tv一起跑马灯需要自定义TV,重写isFocused()
方法返回true
android:ellipsize=”start”—–省略号显示在开头 “…pedia”
android:ellipsize=”end”——省略号显示在结尾 “encyc…”
android:ellipsize=”middle”—-省略号显示在中间 “en…dia”
android:ellipsize=”marquee”–以横向滚动方式显示(需获得当前焦点时)
TextView有值但是width或height为0,导致不显示
(又一城)发生在SBC2.0的燕谷坊的首页的店名,发现用as第一次运行出现这个问题“(debug模式取到值)TextView有值但是width或height为0,导致不显示”。而通过as的Tools-Layout Inspector却得到此TextView的值为“”且width和height为0
尝试解决:textview调用invalidate()、requestLayout()、measure(500,50)、post(Runnable)都不行
后来借鉴stackoverflow相似的问题在xml中在对应TextView中加上
1 | android:animateLayoutChanges="false" |
运行了几次是可以的,但是具体是否解决了这个问题还需待验证。
android:animateLayoutChanges=”false” 的作用是关闭系统带的动画效果
前面我们说过ViewGroup在设置android:animateLayoutChanges="true"
后在添加或者删除子view时可以启用系统带着的动画效果,但这种效果无法通过自定义动画去替换。不过还好android官方为我们提供了LayoutTransition类,通过LayoutTransition就可以很容易为ViewGroup在添加或者删除子view设置自定义动画的过渡效果了。