android中自动适应宽度的TextView

小弟,最近遇到的项目里面有一个需求比较多,就是一个textview只显示一行,如果文字太多显示不下需要缩小字体大小来显示。为此,在网上我也找了挺多的,但是有点问题,都有点不能满足我的需求,在github上面也有一个开源的项目,但是太大了,代码太多,很难阅读,所以我就简单的搞了一下,我重写了一下textview的ondraw方法来重新计算textview宽度到适应宽度,不过这个东西目前只能满足单行的调整,有兴趣的朋友可以改改,改成多行的调整。废话就不多说了, 效果图如下。



android中自动适应宽度的TextView_第1张图片



android中自动适应宽度的TextView_第2张图片


最后在看看代码:


MainActiivty(主入口):


package com.jcl.activity;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


import com.jcl.R;


public class MainActivity extends Activity {
private Button a;
private Button b;


@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
a = (Button) findViewById(R.id.a);
b = (Button) findViewById(R.id.b);
a.setOnClickListener(new View.OnClickListener() {


@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this,
LayoutActivity.class);
startActivity(intent);
}
});
b.setOnClickListener(new View.OnClickListener() {


@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this,
ListViewActivity.class);
startActivity(intent);
}
});
}
}




ListViewActivity(在listview中使用AutoTextView列子):

package com.jcl.activity;


import java.util.ArrayList;
import java.util.List;


import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;


import com.jcl.R;
import com.jcl.view.AutoTextView;
import com.jcl.view.AutoTextView.ChangeLayoutListener;


public class ListViewActivity extends Activity{
private ListView listView;
private List list = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.b_layout);
listView = (ListView) findViewById(R.id.auto_list);
StringBuffer buffer = new StringBuffer();
for(int i=0;i<5;i++) {
buffer.append("我能自动调整宽度");
list.add(buffer.toString());
}
MyAdapter adapter = new MyAdapter();
listView.setAdapter(adapter);
}

private class MyAdapter extends BaseAdapter implements ChangeLayoutListener{


@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}


@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}


@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Holder holder = null;
if(convertView == null) {
convertView = LayoutInflater.from(ListViewActivity.this).inflate(R.layout.cell, null);
holder = new Holder();
holder.auto = (AutoTextView)convertView.findViewById(R.id.text);
holder.auto.setChangeLayoutListener(this, convertView);
convertView.setTag(holder);
}else {
holder = (Holder) convertView.getTag();
}
holder.index = position;
holder.auto.setText(list.get(position));
return convertView;
}
class Holder {
AutoTextView auto;
int index;
}
@Override
public void isChange(View view, String text) {
// TODO Auto-generated method stub
Holder holder = (Holder)view.getTag();
if(holder!=null) {
holder.auto.setText(list.get(holder.index));
}
}


@Override
public boolean isOk(View view) {
// TODO Auto-generated method stub
return true;
}

}
}


LayoutActivity(在普通layout中使用AutoTextView的列子):

package com.jcl.activity;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;


import com.jcl.R;
import com.jcl.view.AutoTextView;
import com.jcl.view.AutoTextView.ChangeLayoutListener;


public class LayoutActivity extends Activity implements ChangeLayoutListener{
AutoTextView textview;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.a_layout);
textview = (AutoTextView) findViewById(R.id.auto);
textview.setChangeLayoutListener(this, textview);
}


@Override
public void isChange(View view, String text) {
// TODO Auto-generated method stub
if(text!=null&&text.length()>0) {
textview.setText(text);   //重新更新textview
}
}


@Override
public boolean isOk(View view) {
// TODO Auto-generated method stub

return true;  //返回true 否则不会计算
}
}



最后是AutoTextView的源码:

package com.jcl.view;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;


import com.jcl.R;




/**
 * 
 * @author jianchuanli
 *
 * 根据宽度大小自动缩放文字大小(当前只限一行的显示)
 *
 */
public class AutoTextView extends TextView {
private float minTextSize, maxTextSize;
private float DEFAULT_MIN_TEXT_SIZE;
private float DEFAULT_MAX_TEXT_SIZE;
private ChangeLayoutListener listener;
private View parentView;
private int width = 0;
private int oldWidth = 0;
private int height = 0;
private boolean isChangeHeight;     //变化文字的大小后是否跟随文字高度保持同步
public AutoTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = getContext().obtainStyledAttributes(attrs,
R.styleable.AutoTextView);
isChangeHeight = a.getBoolean(
R.styleable.AutoTextView_isChangeHeight, false);
DEFAULT_MIN_TEXT_SIZE = a.getDimension(R.styleable.AutoTextView_minTextSize, 1);
DEFAULT_MAX_TEXT_SIZE = a.getDimension(R.styleable.AutoTextView_maxTextSize, 30);
a.recycle();
initialise();
}


public void setChangeLayoutListener(ChangeLayoutListener listener, View view) {
this.listener = listener;
this.parentView = view;
}

public boolean isChangeHeight() {
return isChangeHeight;
}


public void setChangeHeight(boolean isChangeHeight) {
this.isChangeHeight = isChangeHeight;
}


private void initialise() {
maxTextSize = this.getTextSize();

if (maxTextSize <= DEFAULT_MIN_TEXT_SIZE) {
maxTextSize = DEFAULT_MAX_TEXT_SIZE;
}


minTextSize = DEFAULT_MIN_TEXT_SIZE;
};

/**

* @param text   显示的字符串
  * @param textWidth   textview的宽度
* @param preWidth  textview变化前的宽度
*/


private void resize(String text, int textWidth, int preWidth) {


if(listener!=null) {
if(!listener.isOk(parentView)) {   //是否需要重新计算宽度
return;
}
}
boolean isUpdate = false;
if (textWidth > 0) {
int availableWidth = textWidth - this.getPaddingLeft()
- this.getPaddingRight();
float preSize = getPaint().getTextSize();
float curSize = 0;
curSize = maxTextSize;
getPaint().setTextSize(curSize);
if((curSize > minTextSize)
&& (getPaint().measureText(text) > availableWidth)) { //尝试用最初的字体大小计算宽度是否达到调整的标准

if(preWidth < textWidth) {  //为了避免一直计算,判断当前是从小到大还是从大小
curSize = maxTextSize;   //从小到大,使用最大字体大小计算变化量
}else {
curSize = preSize;   //从大到小或者不变,使用当前的字体大小计算变化量
}
getPaint().setTextSize(curSize);
while ((curSize > minTextSize)
&& (getPaint().measureText(text) > availableWidth)) { //如果符合标准并且当前的大小也需要调整,调整宽度到正好合适
isUpdate = true;
curSize -= 1;
if (curSize <= minTextSize) {
curSize = minTextSize;
getPaint().setTextSize(curSize);
break;
}
getPaint().setTextSize(curSize);


}
if (isUpdate) {  //成功调整完毕,接口通知完成刷新


// invalidate();
if (listener != null) {
listener.isChange(parentView,text);  
}
}
}

}




};




@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
width = getWidth();
if(oldWidth == 0) {
oldWidth = width;
}
if (getWidth() > 0) {
height = getHeight();
resize(getText().toString(), width,oldWidth);
super.onDraw(canvas);
oldWidth = width;


} else {
super.onDraw(canvas);
height = getHeight();
width = getWidth();
resize(getText().toString(), width,oldWidth);
oldWidth = width;
}


}




@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!isChangeHeight && height > 0 && width > 0) {   //保持原有高度不变
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), height);

} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);


}
}


public interface ChangeLayoutListener {    //计算前和计算后的监听接口

public void isChange(View view,String text);   //计算完成通知外层刷新
public boolean isOk(View view);   //是否要进行计算
}



}


因为有一些属性设置贴上attr.xml的代码:





  
   
       
       
       
       
   







你可能感兴趣的:(android中自动适应宽度的TextView)