需求描述:

  1. 采用鸿洋大神打造的万能的ListView GridView适配器;
  2. ListView中的item中有一个TextView,该TextView的宽度确定,根据要显示的内容长度动态调整文字的显示方式:不超过1行居中显示;超过1行的话无论第二行有几个字,左对齐显示。效果图如下所示(这里只找到了居中的示例):

刚开始写的item布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/fl_root"android:layout_width="wrap_content"android:layout_height="wrap_content"><RoundedImageViewandroid:id="@+id/iv_image"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:src="@drawable/friendshipislandbg4"android:riv_border_width="0dp"android:riv_corner_radius="8dp" /><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="50dp"android:layout_gravity="bottom"android:background="@drawable/bs_school_name_bg"android:gravity="center"android:maxLines="2"android:paddingLeft="20dp"android:paddingRight="20dp"android:textColor="#ffffff"android:textSize="16sp" /></FrameLayout>
复制代码

动态代码调整TextView的Gravity代码如下:

     @Overridepublic void convert(ListviewViewHolder holder, TempDataBean item) {FrameLayout flRoot = (FrameLayout) holder.getView(R.id.fl_root);//动态调整GridView中每一个item的大小,防止图片大小不同导致每一个item的大小不同ViewGroup.LayoutParams params = flRoot.getLayoutParams();params.height = displayWidth / 2 - MyUtils.dip2px(ctx, 18);params.width = displayWidth / 2 - MyUtils.dip2px(ctx, 18);flRoot.setLayoutParams(params);flRoot.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(BSItemActivity.this, BSDetailActivity.class));}});//显示图片mImageLoader.displayImage(item.getSchoolImage(), (ImageView) holder.getView(R.id.iv_school_image), options, mImageLoadingListener);//用来判断是学校名字是一行或者两行holder.setText(R.id.tv_name, item.getName());TextView tv = (TextView) holder.getView(R.id.tv_name);int lineCount = tv.getLineCount();if(lineCount<=1){//  1行居中tv.setGravity(Gravity.CENTER);}else{//  2行居左tv.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);}}
复制代码

编译,安装,跑起来,发现并不是预期的效果。现在的效果是第一次进入页面,未滑动,无论是一行还是两行都是居中显示。将第一屏滑出界面,并再次滑入界面的时候,1行的居中,2行的居左(符合预期)。我擦,这是什么情况。带着疑问,我将怀疑的目光转向了大神造的轮子。

public static ListviewViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {if (convertView == null) {View itemView = LayoutInflater.from(context).inflate(layoutId, parent,false);ListviewViewHolder holder = new ListviewViewHolder(context, itemView, parent, position);holder.mLayoutId = layoutId;return holder;} else {ListviewViewHolder holder = (ListviewViewHolder) convertView.getTag();holder.mPosttion = position;return holder;}
}
复制代码

我怀疑这段代码是不是少了一些东西,大神没有考虑到可能会有动态修改布局的操作,而仅仅在public void convert(ListviewViewHolder holder, TempDataBean item)方法中考虑了数据替换的操作。

我又怀疑是不是使用LayoutInflater填充出来的View和复用的convertView有一些不同。难道应该在使用LayoutInflater进行填充View的时候就进行动态修改布局的操作,对复用的convertView修改布局参数莫非晚了?说干就干,我就写了一个抽象类,在使用LayoutInflater填充出View之后立即对View进行修改布局操作。抽象类如下:

public abstract class SetLayoutProperty {View itemView;int position;//获得填充出来的View及对应的位置public void setItemView(View itemView, int position) {this.itemView = itemView;this.position = position;}//动态改变布局参数的具体操作public abstract void setLayoutProperty();public View getItemView() {return this.itemView;}public int getPosition() {return position;}
}
复制代码

然后修改了大神造的ViewHolder如下:

public static ListviewViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position,SetLayoutProperty setLayoutProperty) {if (convertView == null) {View itemView = LayoutInflater.from(context).inflate(layoutId, parent,false);//主要增加了这个语句块if (setLayoutProperty != null) {setLayoutProperty.setItemView(itemView,position);setLayoutProperty.setLayoutProperty();}ListviewViewHolder holder = new ListviewViewHolder(context, itemView, parent, position);holder.mLayoutId = layoutId;return holder;} else {ListviewViewHolder holder = (ListviewViewHolder) convertView.getTag();holder.mPosttion = position;return holder;}
}
复制代码

由代码可以看出,如果抽象类不为空,说明具体操作实现了这个抽象类,调用setLayoutProperty.setItemView(itemView,position)方法将需要的内容传出,调用setLayoutProperty.setLayoutProperty()方法将执行具体的修改布局参数的逻辑。

又修改了大神造的Adapter如下:

/*** 在复用之前(展示之前)对一些布局参数进行调整** @return*/
public SetLayoutProperty setLayoutProperty() {return null;
}
复制代码

使用轮子的时候我选择这样写:

      @Overridepublic SetLayoutProperty setLayoutProperty() {return new SetLayoutProperty() {@Overridepublic void setLayoutProperty() {//获取条目布局View itemView = this.getItemView();TextView tv = (TextView) itemView.findViewById(R.id.tv_school_name);tv.setText(datas.get(getPosition()).getSchoolName());int lineCount = tv.getLineCount();LogSwitchUtils.logD(BSItemActivity.class,"学校名字的内容为:"+datas.get(getPosition()).getSchoolName());LogSwitchUtils.logD(BSItemActivity.class,"学校名字的行数为:"+lineCount);if (lineCount <= 1) {tv.setGravity(Gravity.CENTER);} else {tv.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);}}};}@Overridepublic void convert(ListviewViewHolder holder, TempDataBean item) {...}
复制代码

效果是:无论是否滑出或者滑入,无论是1行还是2行,都是居中显示。 通过打印的日志,我发现通过getLineCount()方法获得的数值都为0。不应该啊,让我看看这个方法,于是就发现:

/*** Return the number of lines of text, or 0 if the internal Layout has not* been built.*/
public int getLineCount() {return mLayout != null ? mLayout.getLineCount() : 0;
}
复制代码

我了个去,此时此刻我只想知道如何让 The internal Layout has been built.或者什么时候The internal Layout has been built.

于是乎,我就找度娘,我给度娘说:Return the number of lines of text, or 0 if the internal Layout has not been built.然后度娘没有告诉我想要的答案:即如何让?或者什么时候?

我又接着问度娘:“getlinecount一直是0?”

度娘说了:TextView可以通过getLineCount获取行数,但是这里要在控件绘画后才能获取,否则调用这个函数返回值为0。但是我想在addText时就获得text的行数,这样我可以控制TextView的高度,请问有没有一些开源的代码或者想法可以实现在addText获取行数呢?

哈哈哈哈....在知乎我知道了什么时候获取行数不为0,代码如下。

final TextView totalTitleNo = (TextView) findViewById(R.id.tv_ac_sub_account);
ViewTreeObserver vto = totalTitleNo.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {int lineCount = totalTitleNo.getLineCount();System.out.println(lineCount);}
});
复制代码

迫不及待,我赶紧试试:

      @Overridepublic void convert(ListviewViewHolder holder, TempDataBean item) {FrameLayout flRoot = (FrameLayout) holder.getView(R.id.root_fl);ViewGroup.LayoutParams params = flRoot.getLayoutParams();params.height = displayWidth / 2 - MyUtils.dip2px(ctx, 18);params.width = displayWidth / 2 - MyUtils.dip2px(ctx, 18);flRoot.setLayoutParams(params);flRoot.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(BSItemActivity.this, BSDetailActivity.class));}});//显示图片mImageLoader.displayImage(item.getSchoolImage(), (ImageView) holder.getView(R.id.iv_school_image), options, mImageLoadingListener);//为测试的控件设置值,用来判断是学校名字是一行或者两行holder.setText(R.id.tv_school_name, item.getSchoolName());final TextView tv = (TextView) holder.getView(R.id.tv_school_name);ViewTreeObserver vto = tv.getViewTreeObserver();//这个监听器看名字也知道了,就是在绘画完成之前调用的,在这里面可以获取到行数,当然也可以获取到宽高等信息。vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {int lineCount = tv.getLineCount();LogSwitchUtils.logD(BSItemActivity.class, "学校名字的行数为:" + lineCount);if (lineCount <= 1) {tv.setGravity(Gravity.CENTER);//tv.invalidate();} else {tv.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);//tv.invalidate();}return true;}});}
复制代码

一开始,我的最后一句代码是return false;但发现不行,该界面显示不出来但一直打Log,于是就选择返回了true。

一开始,最后一个注释其实并不是注释,但是当我将它注释掉,发现结果依然是正确的,它就成了注释。

在解决问题的时候,我还问过度娘:android Textview 一行居中,两行居左?

检索度娘得到了如下使用布局文件使TextView实现一行居中,两行居左的效果:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/root_fl"android:layout_width="wrap_content"android:layout_height="wrap_content"><com.makeramen.roundedimageview.RoundedImageViewandroid:id="@+id/iv_school_image"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:src="@drawable/friendshipislandbg4"app:riv_border_width="0dp"app:riv_corner_radius="8dp" />//该层使文字显示在底部<RelativeLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:background="@drawable/bs_school_name_bg"android:layout_gravity="bottom"><LinearLayout//该层使单行居中android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:orientation="vertical"><TextView//该层使两行居左android:paddingLeft="20dp"android:paddingRight="20dp"android:id="@+id/tv_school_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="left"android:maxLines="2"android:textColor="#ffffff"android:textSize="16sp" /></LinearLayout></RelativeLayout></FrameLayout>
复制代码

至此,实现【Android Textview 一行居中 两行居左】需求时我的所想,所做,所得都记录在了这里,便于以后复习。

结论

  1. 大神造的轮子没有错,是自己的理解有错。但敢于向权威质疑的精神是对的,在修改轮子的时候,顺便练习了使用抽象类和接口的使用;
  2. 实现TextView的单行居中,两行居左方法有:动态调整布局参数;完善布局文件;
  3. 深刻体会了textview.getLineCount()方法。

Android Textview 一行居中 两行居左相关推荐

  1. 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  2. CSS实现文字少居中换行居左

    "用 css 对一行文字进行布局,当文字不够换行的时候,这行文字要居中显示,当文字出现换行的时候,这行文字要靠左显示." 效果如上,如果直接居中的话会出现这种效果: 实现方式如下: ...

  3. android textview动态居中,android 设置textview文字居中或者控件居中

    有2种方法可以设置TextView文字居中: 一:在xml文件设置:android:gravity="center" 二:在程序中设置:txtTitle.setGravity(Gr ...

  4. 页面某个模块的文字内容是动态的,可能是几个字,也可能是一句话。然 后,希望文字少的时候居中显示,文字超过一行的时候居左显示。该如何实现?...

    text-align属性只能在内联元素 <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  5. android textview 文字居中_Android布局优化,看这3点就够了

    码个蛋(codeegg)第 712 次推文 作者:Android技术 博客:https://www.jianshu.com/p/2ee61b88175e 前言 在编写Android布局时总会遇到这样或 ...

  6. android textview 文字居中无效,android – 不能垂直居中textview的文本

    [已解决]我不得不向ScrollView添加 android:fillViewport ="true",修复了文本没有垂直居中的问题. 我知道之前已经多次回答,但我仍然无法垂直居中 ...

  7. 解决Android TextView 一行未完全显示就换行问题

    Android api 23以上新增android:breakStrategy属性,用来控制段落布局 当结尾数字.半全角符号.英文字符导致的未显示全而导致的自动换行,可添加android:breakS ...

  8. android顶部居中,如何将drawableLeft对齐到顶部,而不是在android TextView中居中?

    见 my answer here. 您可以通过创建包装您的Drawable的自定义Drawable,然后通过覆盖方法onDraw(Canvas)来操作您的自定义Drawable的绘图来将一个复合Dra ...

  9. Android TextView详解(一)

    TextView简介 在Android应用中,我们通常使用TextView向用户展示文本信息,并可设置文字的字体大小.颜色.背景色等基本样式,本篇我们将学习TextView的一些常用操作和属性. 下面 ...

最新文章

  1. 英国JIC院士3.8万英镑招博后-植物代谢物与微生物组-截止6月27日
  2. JDK1.1 JDK1.2 JDK1.3 JDK1.4 JDK1.5 JDK1.6 JDK1.7
  3. Canvas制作排序算法演示动画
  4. 【牛客 - 315C】排列(思维,贪心,同优则立证明法)
  5. mysql 装载dump文件_mysql命令、mysqldump命令找不到解决
  6. ado mysql 读写_C#使用Ado.Net读写数据库
  7. c语言商品货架管理_武威树脂蔬菜货架厂家价格,生鲜市场货架报价_欧固隆货架...
  8. 解决listview addheader EditText焦点问题
  9. 代码查看工具_不好用打我 | 六个前端开发在线工具推荐
  10. python 网络爬虫 第一天
  11. handler更新ui线程的基本用法
  12. 尼得科向全新的伺服技术挑战
  13. Excel如何从身份证号码中提取性别
  14. PHP获取当前完整网址加HTTP/HTTPS
  15. html安装网卡驱动,教您怎么用驱动精灵安装网卡驱动
  16. 【日常点滴013】python雪球网沪深港美股情爬取
  17. 计算机英语中bar是什么意思啊,bar是什么意思
  18. Dynamics CRM IFD部署后延长系统注销时间
  19. C语言编程从键盘输入n值
  20. caffe配置 一生不可自决

热门文章

  1. 东方卫视演得泰坦机器人_东方卫视《笑傲江湖4》今晚开播,郭德纲、陈赫过招喜剧新人,机器人脱口秀惊艳全场...
  2. typescript设置只读属性和任意类型
  3. webstorm设置文件类型
  4. nginx配置静态资源访问路径
  5. echarts中国地图线性动画特效
  6. JDK,JRE,JVM,JIT
  7. mysql数据库优化课程---13、mysql基础操作
  8. android程序运行无操作一段时间显示屏保
  9. C++类中的封装-9
  10. Visual Assist X插件