需求描述: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()
方法。