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