需求描述:android
刚开始写的item布局文件以下:app
<?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">
<RoundedImageView
android: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" />
<TextView
android: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代码以下:ide
@Override
public 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() {
@Override
public 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以下:ui
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()
方法将执行具体的修改布局参数的逻辑。this
又修改了大神造的Adapter以下:spa
/**
* 在复用以前(展现以前)对一些布局参数进行调整
*
* @return
*/
public SetLayoutProperty setLayoutProperty() {
return null;
}
复制代码
使用轮子的时候我选择这样写:.net
@Override
public SetLayoutProperty setLayoutProperty() {
return new SetLayoutProperty() {
@Override
public 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);
}
}
};
}
@Override
public 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() {
@Override
public boolean onPreDraw() {
int lineCount = totalTitleNo.getLineCount();
System.out.println(lineCount);
}
});
复制代码
火烧眉毛,我赶忙试试:
@Override
public 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() {
@Override
public 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() {
@Override
public 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.RoundedImageView
android: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" />
//该层使文字显示在底部
<RelativeLayout
android: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 一行居中 两行居左】需求时个人所想,所作,所得都记录在了这里,便于之后复习。
textview.getLineCount()
方法。