• 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("
    ")){  
                    List<String> totalList=new ArrayList<String>(10);  
                    String[] str=text.split("
    ");  
                    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("
    ", 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("
    ", "").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("
    ", "").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("
    ");
            }
            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("
    ");
                        }
                        buffer.close();
                        fileText = stringBuilder.toString();
                    }
    				pageSystem = new PageSystem(MainActivity.this, MainActivity.this, fileText);
    				pageSystem.goToPage(value);
                mEditor.setText(pageSystem.getCurrentPageText());
    
  • 相关阅读:
    CentOS中文件夹基本操作命令
    Apache和Nginx下禁止访问特定的目录或文件
    自适应网页设计(Responsive Web Design)
    使用Google Https搜索
    AMD 3600+ X2 CPU配合昂达A69T主板超频教程
    dedecms上传图片相对路径改成绝对路径方法
    安装ecshop默认安装后的错误解决方案
    动态加载JS脚本的4种方法
    Java虚拟机(二)对象的创建与OOP-Klass模型
    Android系统启动流程(四)Launcher启动过程与系统启动流程
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6150664.html
Copyright © 2020-2023  润新知