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());

 

posted @ 2016-05-03 17:05  HappyCode002  阅读(529)  评论(0编辑  收藏  举报