zoukankan      html  css  js  c++  java
  • android中自定义view---实现竖直方向的文字功能,文字方向朝上,同时提供接口,判断当前touch的是哪个字符,并改变颜色

    android自定义view,实现竖直方向的文字功能,文字方向朝上,同时提供接口,判断当前touch的是哪个字符,并改变颜色。

    由于时间比较仓促,因此没有对代码进行过多的优化,功能远远不如android的自带的TextView强大,只是继承于view,而不是textview。

    主要用途:电话本的侧边快速导航等

    效果图:(自定义字符串 “#ABCDEFGHIJKLMN),可以实现自定义任意字符串

    view的实现:

      1 package cn.carbs.verticalstraighttextview.view;
      2 
      3 import cn.carbs.verticalstraighttextview.R;
      4 import android.content.Context;
      5 import android.content.res.TypedArray;
      6 import android.graphics.Canvas;
      7 import android.graphics.Paint.Align;
      8 import android.graphics.Rect;
      9 import android.text.TextPaint;
     10 import android.util.AttributeSet;
     11 import android.util.Log;
     12 import android.util.TypedValue;
     13 import android.view.View;
     14 /**
     15  * 参考资料:
     16  *         http://chris.banes.me/2014/03/27/measuring-text/
     17  *         http://blog.163.com/gobby_1110/blog/static/2928171520136304172378/
     18  * @author Rick.Wang
     19  *
     20  */
     21 public class VerticalStraightTextView extends View {
     22     
     23     private final static int DEFAULT_TEXT_SIZE = 15;  
     24     private final static int DEFAULT_TEXT_COLOR = 0xFF000000;
     25     private final static int DEFAULT_TEXT_COLOR_PICKED = 0xFF990000;
     26     private final static int DEFAULT_CHAR_SPACE = 0;
     27     
     28     private TextPaint mTextPaint;  
     29     private TextPaint mTextPaintPicked;
     30     private String mText = "";
     31     
     32     private int mTextLength = 0;
     33     private int mCharGap = 0;
     34     private int mCharWidth = 0;
     35     private int mCharHeight = 0;
     36     
     37     private int currPickedCharIndex = -1;
     38     
     39     float[] coordinates = null;
     40     
     41     public float[] getCoordinates(){
     42         return coordinates;
     43     }
     44     
     45     public VerticalStraightTextView(Context context) {  
     46         super(context);  
     47         init();  
     48     }  
     49   
     50     public VerticalStraightTextView(Context context, AttributeSet attrs) {  
     51         super(context, attrs);  
     52         init();  
     53   
     54         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.verticalstraighttextview);  
     55         
     56         int n = a.getIndexCount();  
     57         for (int i = 0; i < n; i++) {
     58             int attr = a.getIndex(i);  
     59             switch (attr) {  
     60             case R.styleable.verticalstraighttextview_text:
     61                 mText = a.getString(attr);
     62                 if(mText == null){
     63                     mText = "";
     64                     break;
     65                 }
     66                 mTextLength = mText.length();
     67                 break;  
     68             case R.styleable.verticalstraighttextview_textSize:  
     69                 int textSize = a.getDimensionPixelOffset(R.styleable.verticalstraighttextview_textSize, DEFAULT_TEXT_SIZE);  
     70                 if (textSize > 0) {
     71                     mTextPaint.setTextSize(textSize);
     72                     mTextPaintPicked.setTextSize(textSize);
     73                 }
     74                 break;  
     75 
     76             case R.styleable.verticalstraighttextview_charGap:
     77                 mCharGap = a.getDimensionPixelSize(R.styleable.verticalstraighttextview_charGap, (int) TypedValue.applyDimension(  
     78                         TypedValue.COMPLEX_UNIT_PX, DEFAULT_CHAR_SPACE, getResources().getDisplayMetrics())); 
     79                 break;  
     80             case R.styleable.verticalstraighttextview_textColor:  
     81                 mTextPaint.setColor(a.getColor(R.styleable.verticalstraighttextview_textColor, DEFAULT_TEXT_COLOR));
     82                 break;  
     83             case R.styleable.verticalstraighttextview_textColorPicked:  
     84                 mTextPaintPicked.setColor(a.getColor(R.styleable.verticalstraighttextview_textColorPicked, DEFAULT_TEXT_COLOR_PICKED));
     85                 break;  
     86             }  
     87         }  
     88         a.recycle();  
     89         
     90         requestLayout();  
     91         invalidate();  
     92     }  
     93   
     94     private final void init() {  
     95         mTextPaint = new TextPaint();  
     96         mTextPaint.setAntiAlias(true);  
     97         mTextPaint.setTextSize(DEFAULT_TEXT_SIZE);  
     98         mTextPaint.setTextAlign(Align.CENTER);
     99         mTextPaintPicked = new TextPaint(mTextPaint);
    100         mTextPaint.setColor(DEFAULT_TEXT_COLOR);
    101         mTextPaintPicked.setColor(DEFAULT_TEXT_COLOR_PICKED);
    102     }  
    103   
    104     public void setText(String text) {
    105         if(text == null){
    106             text = "";
    107         }
    108         if(!mText.equals(text)){
    109             mText = text;  
    110             mTextLength = text.length();
    111             requestLayout();  
    112             invalidate();  
    113         }
    114     }  
    115   
    116     public void setTextSize(int size) {
    117         if(mTextPaint.getTextSize() != size){
    118             mTextPaint.setTextSize(size);  
    119             mTextPaintPicked.setTextSize(size);
    120             requestLayout();  
    121             invalidate();  
    122         }
    123     }  
    124   
    125     public void setTextColor(int color) {
    126         if(color != mTextPaint.getColor()){
    127             mTextPaint.setColor(color);
    128             invalidate();  
    129         }
    130     }
    131     
    132     public void setTextColorPicked(int color) {
    133         if(color != mTextPaintPicked.getColor()){
    134             mTextPaintPicked.setColor(color);
    135             invalidate();  
    136         }
    137     }
    138     
    139     public int getCharHeight(){
    140         return mCharGap + mCharHeight;
    141     }
    142   
    143     @Override  
    144     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
    145         Log.d("1218", "onMeasure");
    146         //获取字体宽度
    147         float maxCharWidth = 0f;
    148         for(int i = 0; i < mTextLength; i++){
    149              maxCharWidth = Math.max(mTextPaint.measureText(mText.substring(i, i+1)), maxCharWidth);
    150         }
    151         mCharWidth = (int)Math.ceil(maxCharWidth);
    152         
    153         //获取字体高度
    154         Rect textBounds = new Rect();
    155         mTextPaint.getTextBounds(mText, 0, mTextLength, textBounds);
    156         mCharHeight = textBounds.height();
    157         
    158         setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    159     }
    160     
    161     private int measureWidth(int measureSpec) {  
    162         int result = 0;  
    163         int specMode = MeasureSpec.getMode(measureSpec);  
    164         int specSize = MeasureSpec.getSize(measureSpec);  
    165   
    166         if (specMode == MeasureSpec.EXACTLY) {  
    167             result = specSize;
    168         } else {  
    169             result = this.getPaddingLeft() + this.getPaddingRight() + mCharWidth;
    170             if (specMode == MeasureSpec.AT_MOST) {
    171                 result = Math.min(result, specSize);  
    172             }
    173         }
    174         return result;  
    175     }  
    176   
    177     private int measureHeight(int measureSpec) {  
    178         int result = 0;  
    179         int specMode = MeasureSpec.getMode(measureSpec);  
    180         int specSize = MeasureSpec.getSize(measureSpec);  
    181 
    182         if (specMode == MeasureSpec.EXACTLY) {  
    183             result = specSize;  
    184         } else {  
    185             result = getPaddingTop() + getPaddingBottom();
    186             if(mTextLength > 0){
    187                 result += mTextLength * (mCharGap + mCharHeight) - mCharGap;
    188             }
    189             if (specMode == MeasureSpec.AT_MOST) {  
    190                 result = Math.min(result, specSize);  
    191             }  
    192         }  
    193         return result;
    194     }  
    195 
    196     @Override  
    197     protected void onDraw(Canvas canvas) {  
    198         super.onDraw(canvas);  
    199         Log.d("1218", "onDraw");
    200         if(mTextLength == 0){
    201             return;
    202         }
    203         
    204         int height = getMeasuredHeight();
    205         int measuredWidth = getMeasuredWidth();
    206         
    207         int paddingTop = getPaddingTop();
    208         int paddingBottom = getPaddingBottom();
    209         int paddingLeft = getPaddingLeft();
    210         int paddingRight = getPaddingRight();
    211         
    212         //默认居中
    213         int x = paddingLeft + (measuredWidth - paddingLeft - paddingRight)/2;
    214         int y = 0;
    215         
    216         int cellHeight = (height - paddingTop - paddingBottom)/ mTextLength;
    217         //TODO 可能会有bug
    218         if(coordinates == null || coordinates.length != mTextLength){
    219             coordinates = new float[mTextLength + 1];
    220         }
    221         coordinates[0] = 0;
    222         for(int i = 0; i < mTextLength; i++){
    223             y = paddingTop + i * cellHeight + cellHeight/2;
    224             coordinates[i + 1] = y + cellHeight/2;
    225             if(currPickedCharIndex != i){
    226                 canvas.drawText(mText, i, i + 1, x, y, mTextPaint);
    227             }else{
    228                 canvas.drawText(mText, i, i + 1, x, y, mTextPaintPicked);
    229             }
    230         }
    231         coordinates[mTextLength] = height;
    232     }
    233     
    234     //y is the coordinate-Y
    235     //this function can return the "touched char"
    236     public int getPickedCharIndex(float[] coordinates, float y){
    237         int start = 0;
    238         int end = coordinates.length - 1;
    239         while (start != end - 1) {
    240             int middle = (start + end) / 2;
    241             if (y < coordinates[middle]) {
    242                 end = middle;
    243             } else if (y > coordinates[middle]) {
    244                 start = middle;
    245             }
    246         }
    247         return start;
    248     }
    249     
    250     
    251     /***************************************
    252      * 
    253      *         +---------------+  <-- Y == coordinates[0]
    254      *         |        #        |
    255      *         |---------------|            coordinates[1]
    256      *         |        A        |
    257      *         |---------------|            coordinates[2]
    258      *         |        B        |
    259      *         |---------------|            coordinates[3]
    260      *         |        C        |
    261      *         +---------------|            coordinates[4]
    262      ***************************************/
    263     
    264     public int getPickedCharIndex(float y){
    265         //优化查询
    266         //如果当前的>-1,说明正在touchEvent
    267         if(currPickedCharIndex > -1){
    268             if(coordinates[currPickedCharIndex] < y && y < coordinates[currPickedCharIndex+1]){
    269                 return currPickedCharIndex;
    270             }
    271         }
    272         
    273         int start = 0;
    274         int end = coordinates.length - 1;
    275         while (start != end - 1) {
    276             int middle = (start + end) / 2;
    277             if (y < coordinates[middle]) {
    278                 end = middle;
    279             } else if (y > coordinates[middle]) {
    280                 start = middle;
    281             }
    282         }
    283         return start;
    284     }
    285     
    286     
    287     public void setCurrPickedCharIndex(int index){
    288         if(currPickedCharIndex != index){
    289             currPickedCharIndex = index;
    290             invalidate();
    291         }
    292     }
    293 
    294 }  

    style文件的定义:(将此代码写入values文件夹下的styles.xml文件中)

    1 <declare-styleable name="verticalstraighttextview">
    2         <attr name= "text" format ="string" />
    3         <attr name= "textColor" format ="reference|color" />
    4         <attr name= "textColorPicked" format="reference|color" />
    5         <attr name= "textSize" format="reference|dimension" />
    6         <attr name= "charGap" format ="reference|dimension" />
    7     </declare-styleable >

    布局文件引入此自定义view:

    1 <cn.carbs.verticalstraighttextview.view.VerticalStraightTextView
    2         android:id="@+id/kk"
    3         android:layout_width="wrap_content"
    4         android:padding="5dp"
    5         android:layout_height="fill_parent"
    6         android:background="#33333333"
    7         app:textSize="20sp"
    8         app:text= "#ABCEDFGHIJKLMN" />

    在activity中的使用:

     1 verticalView = (VerticalStraightTextView)this.findViewById(R.id.kk);
     2         
     3         verticalView.setOnClickListener(new View.OnClickListener() {
     4             @Override
     5             public void onClick(View v) {
     6                 Toast.makeText(getApplicationContext(), "onclick", Toast.LENGTH_SHORT).show();
     7             }
     8         });
     9        
    10         verticalView.setOnTouchListener(new View.OnTouchListener() {
    11             
    12             @Override
    13             public boolean onTouch(View view, MotionEvent event) {
    14                 switch(event.getAction()){
    15                 case MotionEvent.ACTION_DOWN:
    16                     verticalView.setCurrPickedCharIndex(verticalView.getPickedCharIndex(event.getY()));
    17                     break;
    18                 case MotionEvent.ACTION_MOVE:
    19                     verticalView.setCurrPickedCharIndex(verticalView.getPickedCharIndex(event.getY()));
    20                     break;
    21                 case MotionEvent.ACTION_UP:
    22                     verticalView.setCurrPickedCharIndex(-1);
    23                     break;
    24                 case MotionEvent.ACTION_CANCEL:
    25                     verticalView.setCurrPickedCharIndex(-1);
    26                     break;
    27                 }
    28                 return true;
    29             }
    30         });
  • 相关阅读:
    JVM 基础知识
    Maven 学习
    Java 中 split() 方法
    JDK、JRE、JVM三者联系与区别
    Effective C++ 笔记 —— Item 5: Know what functions C++ silently writes and calls
    Effective C++ 笔记 —— Item 4: Make sure that objects are initialized before they’re used
    Effective C++ 笔记 —— Item 3: Use const whenever possible
    Effective C++ 笔记 —— Item 2: Prefer consts, enums, and inlines to #defines
    Idea社区版使用插件完成正常开发
    DNS配置
  • 原文地址:https://www.cnblogs.com/carbs/p/5056568.html
Copyright © 2011-2022 走看看