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         });
  • 相关阅读:
    VOA 2009/11/02 DEVELOPMENT REPORT In Kenya, a Better Life Through Mobile Money
    2009.11.26教育报道在美留学生数量创历史新高
    Java中如何实现Tree的数据结构算法
    The Python Tutorial
    VOA HEALTH REPORT Debate Over New Guidelines for Breast Cancer Screening
    VOA ECONOMICS REPORT Nearly Half of US Jobs Now Held by Women
    VOA ECONOMICS REPORT Junior Achievement Marks 90 Years of Business Education
    VOA 2009/11/07 IN THE NEWS A Second Term for Karzai; US Jobless Rate at 10.2%
    Ant入门
    Python 与系统管理
  • 原文地址:https://www.cnblogs.com/carbs/p/5056568.html
Copyright © 2011-2022 走看看