android TextView相关属性及文本处理
Edittext响应onclick,由于click事件被onTouchEvent拦截,所以通过设置touch事件监听处理
// et_more.setOnTouchListener(new OnTouchListener() {
// @Override
// public boolean onTouch(View v, MotionEvent event) {
// if(MotionEvent.ACTION_UP==event.getAction()){
// ....
}
// return false;
// }
// });
EditText设置enable为false时,不响应ontouch事件,但又进行了事件拦截,没有传递给parent ViewGroup ,由于在onTouchEvent事件没有对enable状态判断,
所以事件仍然在onTouchEvent rerurn true。解决重写EditText的onTouchEvent 增加isEnable判断即可:
public class EditTextTouch extends EditText {
public EditTextTouch(Context context) {
this(context, null);
}
public EditTextTouch(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return isEnabled() && super.onTouchEvent(event);
}
}
EditText代码实现动态设置输入类型:
setInputType(InputType.TYPE_CLASS_PHONE);
setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
自定义类型 通过setKeyListener()
setKeyListener(new MyNumberType());
private class MyNumberType extends NumberKeyListener {
@NonNull
@Override
protected char[] getAcceptedChars() {//限制内容
char[] numberChars={'1','2','3','4','5','6','7','8','9','.','0',};
return numberChars;
}
@Override
public int getInputType() {
return android.text.InputType.TYPE_CLASS_PHONE;
}
}
限定输入字符
xml中我们可以使用digits属性可以实现字符的限定,代码中EditText提供setKeyListener(KeyListener )和setFilters(InputFilter[])两个方法
setFilters
如限制输入输入字数为8
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(8)});
只能输入8位大写字母
editText.setFilters(new InputFilter[]{new InputFilter.AllCaps(),new InputFilter.LengthFilter(8)});
InputFilter switchFilter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
return source.toString().toUpperCase();
}
};
editText.setFilters(new InputFilter[]{switchFilter,new InputFilter.LengthFilter(16)});
setKeyListener方式
InputFilter提供了字符过滤,KeyListener提供了对输入键盘按键的监听。
DigitsKeyListener、NumberKeyListener是我们经常使用的,DigitsKeyListener继承了NumberKeyListener,NumberKeyListener实现了InputFilter,
所以我们在使用InputFilter的时候发现也可以设置DigitsKeyListener和NumberKeyListener
//https://blog.csdn.net/xuwb123xuwb/article/details/71081174
//https://www.jianshu.com/p/bd4273c12e5b
textview 设置图片两种方式:
TextView textView=null;
1, int flagResId = getResources().getIdentifier("icon", "drawable", getPackageName());
textView.setCompoundDrawablesWithIntrinsicBounds(flagResId, 0, 0, 0);
2, Drawable drawable = mContext.getResources().getDrawable(R.drawable.shop_arrow_down);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
textView.setCompoundDrawables(null, null, drawable, null);
TextView控件的背景透明度和字体透明度
方式1, tv.setBackgroundColor(Color.argb(255, 0, 255, 0)); //背景透明度 tv.setTextColor(Color.argb(255, 0, 255, 0)); //文字透明度 方式2, tv.setTextColor(0xffff00ff);
0xffff00ff是int类型的数据,分组一下0x|ff|ff00ff,0x是代表颜色整数的标记,ff是表示透明度,ff00ff表示颜色,注意:这里ffff00ff必须是8个的颜色表示
原理,把透明度转换为色值。就是根据透明度转换为色值,放在前两位
透明度转换可以参照下表: 透明度 对应十六进制 100% ff 90% e6 85% d9 80% cc 70% b3 60% 99 50% 80 40% 66 30% 4d 20% 33 15% 26 10% 1a 5% 0d 0% 00
代码设置EditText输入限制:
public void setNumInputType(String str){
//digits="0123456789" 只数字
//"0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 字母+数字
etInput.setKeyListener(DigitsKeyListener.getInstance(str));
}
// etInput.setInputType(InputType.TYPE_CLASS_NUMBER);//数字键盘
// InputType.TYPE_TEXT_FLAG_MULTI_LINE);//设置输入类型和键盘为英文
// etInput.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
one textView different text style
String s= "Hello Everyone"; SpannableString ss1= new SpannableString(s); ss1.setSpan(new RelativeSizeSpan(2f), 0,5, 0); // set size ss1.setSpan(new ForegroundColorSpan(Color.RED), 0, 5, 0);// set color TextView tv= (TextView) findViewById(R.id.textview); tv.setText(ss1);
textView.setText(Html.fromHtml("<b>myLogin</b> <i>logout</i>"));SpannableString styledString = new SpannableString("myLogin logout");
styledString.setSpan(new StyleSpan(Typeface.BOLD), 0, 7, 0);
styledString.setSpan(new StyleSpan(Typeface.ITALIC), 8, 14, 0);
tv.setText(styledString);
计算字体宽度:
public static float GetTextWidth(String text, float Size) {
TextPaint FontPaint = new TextPaint();
FontPaint.setTextSize(Size);
return FontPaint.measureText(text);
}
// 计算文本,行数,高度
FontMetrics fm = mTextView.getPaint().getFontMetrics();
mFontHeight = (int) (Math.ceil(fm.descent - fm.top) + 2);// 获得每行高度
mPageLineNum = (int) (mTextHeight / mFontHeight);// 获得行数
//TextView 分页设置相关
getLineBounds(int line, Rect bounds) // 得到指定行的边界
只要从第一行开始一行一行往下看, 直到找到超出边界的那一行, 就能知道这个 TextView 能显示多少行了.
或者用 getHeight() / getLineHeight() 也能获取 TextView 的最大显示行数
getLineForVertical(int vertical) // 根据纵坐标得到对应的行号
getLineEnd(int line) // 返回指定行中最后一个字在整个字符串中的位置
一个TextView设置多种颜色文字
Html.fromHtml(String.format(formate, getColorText(params, color)));
public class ReadView extends TextView {
// 构造函数略...
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
resize();
}
/**
* 去除当前页无法显示的字
* @return 去掉的字数
*/
public int resize() {
CharSequence oldContent = getText();
CharSequence newContent = oldContent.subSequence(0, getCharNum());
setText(newContent);
return oldContent.length() - newContent.length();
}
/**
* 获取当前页总字数
*/
public int getCharNum() {
return getLayout().getLineEnd(getLineNum());
}
/**
* 获取当前页总行数
*/
public int getLineNum() {
Layout layout = getLayout();
int topOfLastLine = getHeight() - getPaddingTop() - getPaddingBottom() - getLineHeight();
return layout.getLineForVertical(topOfLastLine);
}
}
//TextView设置完setMaxLines后,通过TextView.getHeight方法获取的是当前行数的高度,而非文字完全显示的高度
//实际获取高度方法
/**
*
* @param pTextView
* @return
*/
private int getTextViewHeight(TextView pTextView) {
Layout layout = pTextView.getLayout();
int desired = layout.getLineTop(pTextView.getLineCount());
int padding = pTextView.getCompoundPaddingTop() + pTextView.getCompoundPaddingBottom();
return desired + padding;
}
//自定义View绘制文本时,格式化文本内容StaticLayout实现:
public void onDraw(Canvas canvas){
super.onDraw(canvas);
TextPaint tp = new TextPaint();
tp.setColor(Color.BLUE);
tp.setStyle(Style.FILL);
tp.setTextSize(50);
String message = "paint,draw paint指用颜色画,如油画颜料、水彩或者水墨画,而draw 通常指用铅笔、钢笔或者粉笔画,后者一般并不涂上颜料。两动词的相应名词分别为p";
StaticLayout myStaticLayout = new StaticLayout(message, tp, canvas.getWidth(), Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
myStaticLayout.draw(canvas);
canvas.restore();
}
自定义view绘制文本计算文本宽度高度:
private Rect mBounds = new Rect();
String text = String.valueOf(mCount);
mPaint.getTextBounds(text, 0, text.length(), mBounds);
float textWidth = mBounds.width();
float textHeight = mBounds.height();
canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + textHeight / 2, mPaint);
文本分割处理
/**
* 自动分割文本
* @param content 需要分割的文本
* @param p 画笔,用来根据字体测量文本的宽度
* @param width 最大的可显示像素(一般为控件的宽度)
* @return 一个字符串数组,保存每行的文本
*/
public static String[] autoSplitText(String content, Paint p, int width) {
float textWidth = p.measureText(content);
if(textWidth <= width) {
return new String[]{content};
}
int length = content.length();
int start = 0, end = 1, i = 0;
int lines = (int) Math.ceil(textWidth / width); //计算行数
String[] lineTexts = new String[lines];
while(start < length) {
if(p.measureText(content, start, end) > width) { //文本宽度超出控件宽度时
lineTexts[i++] = content.substring(start, end);//(String) content.subSequence(start, end);
start = end;
}
if(end == length) { //不足一行的文本
lineTexts[i] = content.substring(start, end);//(String) content.subSequence(start, end);
break;
}
end += 1;
}
return lineTexts;
}
TextView字体间距
1、android:lineSpacingExtra
设置行间距,如”3dp”。
2、android:lineSpacingMultiplier
设置行间距的倍数,如”1.2″。
设置texview 垂直滚动条
android:focusable="true"
android:focusableInTouchMode="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:scrollbars="vertical"
android:singleLine="false"
设置textview 文字水平自动滚动(跑马灯效果)
<com.example.playpic.MyTextView
android:id="@+id/myTv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="#000000"
android:focusable="true"
android:focusableInTouchMode="true"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
/>
布局文件需添加属性:android:addStatesFromChildren="true"
修改的textview
public class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
public boolean isFocused() {
return true;
}
}
setContentView(R.layout.scrollview1);
MyTextView tv=(MyTextView)findViewById(R.id.myTv);
tv.setText(str);
tv.setMovementMethod(ScrollingMovementMethod.getInstance());
android 动态设置TextView值,例:金额增加
public static void autoIncrement(final TextView target, final float start,
final float end, long duration) {
ValueAnimator animator = ValueAnimator.ofFloat(start, end);
animator.addUpdateListener(new AnimatorUpdateListener() {
private FloatEvaluator evalutor = new FloatEvaluator();
private DecimalFormat format = new DecimalFormat("####0.0#");
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
float currentValue = evalutor.evaluate(fraction, start, end);
target.setText(format.format(currentValue));
}
});
animator.setDuration(duration);
animator.start();
}
Textview 设置maxLines>1时,超出部分内容没...省略号解决方法
解决方案:1,自定义实现,2,通过post(Runable r)即在Textview设置文字后显示完计算处理
class OmitTextViewDeal implements Runnable{
TextView tv;
String txt;
public GoodsAttributeTextViewDeal(){
}
@Override
public void run() {
float txtLen=tv.getPaint().measureText(txt);
int tvLen=tv.getWidth();
int lines=Math.round(txtLen/tvLen+0.9f);
if(lines>2){
String[] splitContent= UtilsView.autoSplitText(txt,tv.getPaint(),tvLen);
String ts=splitContent[1].substring(0,splitContent[1].length()-5);
String showTxt=splitContent[0]+ts+"...";
tv.setText(showTxt);
}
}
}
public static String[] autoSplitText(String content, Paint p, int width) {
float textWidth = p.measureText(content);
if(textWidth <= width) {
return new String[]{content};
}
int length = content.length();
int start = 0, end = 1, i = 0;
int lines = (int) Math.ceil(textWidth / width); //计算行数
String[] lineTexts = new String[lines];
while(start < length) {
if(p.measureText(content, start, end) > width) { //文本宽度超出控件宽度时
lineTexts[i++] = content.substring(start, end);//(String) content.subSequence(start, end);
start = end;
}
if(end == length) { //不足一行的文本
lineTexts[i] = content.substring(start, end);//(String) content.subSequence(start, end);
break;
}
end += 1;
}
return lineTexts;
}
使用:
tv_attr.setText(txtAttr);
OmitTextViewDeal attrTvDeal=new OmitTextViewDeal();
attrTvDeal.tv=tv_attr;
attrTvDeal.txt=txtAttr;
holder.tv_attr.post(attrTvDeal);
文本分割处理
/**
* 在文字信息绘制前对文本信息进行文字分割,文字间距,文字位置计算处理
* @param text
*/
private void initDrawText(String text){
if(texts==null){
texts=getTexts(text);
}
if(tposy==null){
tposy=getTextLinePosy();
}
if(stepBack==null){
stepBack=new Float[tposy.length];
int i=0;
float interval=0.0f;
FontMetrics fm = textPaint.getFontMetrics();
float baseline = fm.descent - fm.ascent;
while(i<stepBack.length){
stepBack[i]=interval;
interval-=baseline;
i++;
}
}
if(step==null){
step=stepBack.clone();
}
}
/**
* 获取分割后的文本信息
* @param text
* @return
*/
private String[] getTexts(String text){
if(text.contains("\n")){
List<String> totalList=new ArrayList<String>(10);
String[] str=text.split("\n");
int len=str.length;
for(int i=0;i<len;i++){
String[] ss=autoSplit(str[i], textPaint, getWidth()/3*2);
for(String s:ss){
totalList.add(s);
}
}
if(texts==null)
texts=(String[]) totalList.toArray(new String[0]);
}
else
texts=autoSplit(text, textPaint, getWidth()/3*2);
return texts;
}
/**
* 获取每行文本的纵坐标信息
* @return
*/
private Float[] getTextLinePosy(){
FontMetrics fm = textPaint.getFontMetrics();
float baseline = fm.descent - fm.ascent;
float y = posy+baseline; //由于系统基于字体的底部来绘制文本,所有需要加上字体的高度
int len=texts.length;
Float[] groups=new Float[len];
for(int i=0;i<len;i++) {
groups[i]=y;
y =y+ baseline + fm.leading; //添加字体行间距
}
return groups;
}
/**
* 自动分割文本
* @param content 需要分割的文本
* @param p 画笔,用来根据字体测量文本的宽度
* @param width 最大的可显示像素(一般为控件的宽度)
* @return 一个字符串数组,保存每行的文本
*/
private String[] autoSplit(String content, Paint p, float width) {
float textWidth = p.measureText(content);
if(textWidth <= width) {
return new String[]{content};
}
int length = content.length();
int start = 0, end = 1, i = 0;
int lines = (int) Math.ceil(textWidth / width); //计算行数
String[] lineTexts = new String[lines];
while(start < length) {
if(p.measureText(content, start, end) > width) { //文本宽度超出控件宽度时
lineTexts[i++] = content.substring(start, end);//(String) content.subSequence(start, end);
start = end;
}
if(end == length) { //不足一行的文本
lineTexts[i] = content.substring(start, end);//(String) content.subSequence(start, end);
break;
}
end += 1;
}
return lineTexts;
}
大文本分页显示处理:
package sharedcode.turboeditor.texteditor;
import android.content.Context;
import java.util.LinkedList;
import java.util.List;
import sharedcode.turboeditor.preferences.PreferenceHelper;
public class PageSystem {
private List<String> pages;
private int[] startingLines;
private int currentPage = 0;
private PageSystemInterface pageSystemInterface;
public PageSystem(Context context, PageSystemInterface pageSystemInterface, String text) {
final int charForPage = 20000;
final int firstPageChars = 50000;
this.pageSystemInterface = pageSystemInterface;
pages = new LinkedList<>();
int i = 0;
int to;
int nextIndexOfReturn;
final int textLength = text.length();
boolean pageSystemEnabled = PreferenceHelper.getSplitText(context);
if (pageSystemEnabled) {
while (i < textLength) {
// first page is longer
to = i + (i == 0 ? firstPageChars : charForPage);
nextIndexOfReturn = text.indexOf("\n", to);
if (nextIndexOfReturn > to) to = nextIndexOfReturn;
if (to > text.length()) to = text.length();
pages.add(text.substring(i, to));
i = to + 1;
}
if (i == 0)
pages.add("");
} else {
pages.add(text);
}
startingLines = new int[pages.size()];
setStartingLines();
}
public int getStartingLine() {
return startingLines[currentPage];
}
public String getCurrentPageText() {
return pages.get(currentPage);
}
public String getTextOfNextPages(boolean includeCurrent, int nOfPages) {
StringBuilder stringBuilder = new StringBuilder();
int i;
for (i = includeCurrent ? 0 : 1; i < nOfPages; i++) {
if (pages.size() > (currentPage + i)) {
stringBuilder.append(pages.get(currentPage + 1));
}
}
return stringBuilder.toString();
}
public void savePage(String currentText) {
pages.set(currentPage, currentText);
}
public void nextPage() {
if (!canReadNextPage()) return;
goToPage(currentPage + 1);
}
public void prevPage() {
if (!canReadPrevPage()) return;
goToPage(currentPage - 1);
}
public void goToPage(int page) {
if (page >= pages.size()) page = pages.size() - 1;
if (page < 0) page = 0;
boolean shouldUpdateLines = page > currentPage && canReadNextPage();
if (shouldUpdateLines) {
String text = getCurrentPageText();
int nOfNewLineNow = (text.length() - text.replace("\n", "").length()) + 1; // normally the last line is not counted so we have to add 1
int nOfNewLineBefore = startingLines[currentPage + 1] - startingLines[currentPage];
int difference = nOfNewLineNow - nOfNewLineBefore;
updateStartingLines(currentPage + 1, difference);
}
currentPage = page;
pageSystemInterface.onPageChanged(page);
}
public void setStartingLines() {
int i;
int startingLine;
int nOfNewLines;
String text;
startingLines[0] = 0;
for (i = 1; i < pages.size(); i++) {
text = pages.get(i - 1);
nOfNewLines = text.length() - text.replace("\n", "").length() + 1;
startingLine = startingLines[i - 1] + nOfNewLines;
startingLines[i] = startingLine;
}
}
public void updateStartingLines(int fromPage, int difference) {
if (difference == 0)
return;
int i;
if (fromPage < 1) fromPage = 1;
for (i = fromPage; i < pages.size(); i++) {
startingLines[i] += difference;
}
}
public int getMaxPage() {
return pages.size() - 1;
}
public int getCurrentPage() {
return currentPage;
}
public String getAllText(String currentPageText) {
pages.set(currentPage, currentPageText);
int i;
StringBuilder allText = new StringBuilder();
for (i = 0; i < pages.size(); i++) {
allText.append(pages.get(i));
if(i < pages.size() - 1)
allText.append("\n");
}
return allText.toString();
}
public boolean canReadNextPage() {
return currentPage < pages.size() - 1;
}
public boolean canReadPrevPage() {
return currentPage >= 1;
}
public interface PageSystemInterface {
void onPageChanged(int page);
}
}
use page:
InputStream inputStream = getContentResolver().openInputStream(uri);
if(inputStream != null) {
buffer = new BufferedReader(new InputStreamReader(inputStream, encoding));
}
if (buffer != null) {
while((line = buffer.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append("\n");
}
buffer.close();
fileText = stringBuilder.toString();
}
pageSystem = new PageSystem(MainActivity.this, MainActivity.this, fileText);
pageSystem.goToPage(value);
mEditor.setText(pageSystem.getCurrentPageText());

浙公网安备 33010602011771号