Android自定义竖排TextView实现实例

Android自定义竖排TextView实现实例

前言:

之前做联系人模块的时候遇到一个左侧索引控件,里面的字符都是竖直方向上排列的。当时这个控件是用一个图片代替的。现在想来如果索引的字符变更了,那么就得重新更换图片了,感觉很麻烦。今天通过一个自定义TextView实现类似的功能。先上效果图:

汉字和英文字符都可以竖直排列。结合联系人界面,可以将左侧的索引改成联系人的姓氏。

上代码:

测试用的Activity。

public class MainActivity extends Activity implements OnTouchListener { 

  private VerticalTextView mVerticalTextView; 

  private TextView mTextView; 

  private int mTextCount; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main); 

    mVerticalTextView = (VerticalTextView) findViewById(R.id.vertical_tv);
    mTextView = (TextView) findViewById(R.id.content_tx);
    mTextCount = mVerticalTextView.getText().length();
    mVerticalTextView.setOnTouchListener(this);
    mTextView.setBackgroundColor(Color.LTGRAY);
  } 

  @Override
  public boolean onTouch(View v, MotionEvent event) {
    float verticalTextViewHeight = mVerticalTextView.getHeight();
    float y = event.getY();
    int sectionPosition = (int) Math.ceil((y / verticalTextViewHeight)
        / (1f / mTextCount)) - 1;
    if (sectionPosition < 0) {
      sectionPosition = 0;
    } else if (sectionPosition >= mTextCount) {
      sectionPosition = mTextCount - 1;
    }
    String sectionLetter = String.valueOf(mVerticalTextView.getText()
        .charAt(sectionPosition));
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      mTextView.setVisibility(View.VISIBLE);
      mTextView.setText(sectionLetter);
      break;
    case MotionEvent.ACTION_MOVE:
      mTextView.setText(sectionLetter);
      mTextView.setVisibility(View.VISIBLE);
      break; 

    case MotionEvent.ACTION_UP:
      mTextView.setVisibility(View.INVISIBLE);
    default:
      break; 

    } 

    return true;
  }
}

这里主要说下如何通过点击或者滑动左侧的自定义TextView,将索引值取出来。主要的实现点在代码:

float verticalTextViewHeight = mVerticalTextView.getHeight();
float y = event.getY();
int sectionPosition = (int) Math.ceil((y / verticalTextViewHeight)
    / (1f / mTextCount)) - 1;
if (sectionPosition < 0) {
  sectionPosition = 0;
} else if (sectionPosition >= mTextCount) {
  sectionPosition = mTextCount - 1;
}
String sectionLetter = String.valueOf(mVerticalTextView.getText()
    .charAt(sectionPosition));

这里verticalTextViewHeight 是整个控件的高度,y按下控件后的y轴坐标,然后通过一个比例式将点击位置换算成竖排索引字符集中的对应字符位置,通过这个位置就可以判断出点击的是哪一个索引字符了。这里要注意比例式中的运算要转成浮点型计算,否则无法得到正确的索引值,楼主当时就在此深深的坑过。

下面是重点自定义TextView的实现代码:

public class VerticalTextView extends TextView { 

  /**
   * 绘制整个VerticalTextView区域大小的画笔
   */
  private Paint mPaint;
  /**
   * 绘制每个竖排字符间的间隔横线的画笔
   */
  private Paint linePaint;
  /**
   * 绘制单个字符的画笔
   */
  private Paint charPaint; 

  private char[] indexs; 

  private int textCount; 

  private String textString; 

  public VerticalTextView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  } 

  public VerticalTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle); 

    mPaint = new Paint(); 

    linePaint = new Paint(); 

    charPaint = new Paint(); 

    textString = getText().toString();
    indexs = getKeyChar(textString);
    textCount = textString.toCharArray().length;
  } 

  @Override
  protected void onDraw(Canvas canvas) {
    float childHeight = getHeight() / textCount;
    if (TextUtils.isEmpty(textString))
      return;
    canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
    canvas.drawColor(Color.GRAY); 

    linePaint.setColor(Color.BLACK); 

    charPaint.setTextSize((float) (getWidth() * 0.75));
    charPaint.setTextAlign(Paint.Align.CENTER); 

    FontMetrics fm = charPaint.getFontMetrics();
    for (int i = 0; i < textCount; i++) {
      canvas.drawLine(0, i * childHeight, getWidth(), i * childHeight,
          linePaint);
      canvas.drawText(
          String.valueOf(indexs[i]),
          getWidth() / 2,
          (float) (((i + 0.5) * childHeight) - (fm.ascent + fm.descent) / 2),
          charPaint);
    }
  } 

  protected char[] getKeyChar(String str) {
    char[] keys = new char[str.length()];
    for (int i = 0; i < keys.length; i++) {
      keys[i] = str.charAt(i);
    }
    return keys;
  }
}

代码也很简单,复写了onDraw函数。将要显示的字符串拆分成一个个字符放在一个数组中。通过一个循环遍历这个数组,挨个将他们绘制出来。精华只有一句:

canvas.drawText(String.valueOf(indexs[i]),getWidth() / 2,(float) (((i + 0.5) * childHeight) -  

(fm.ascent + fm.descent) / 2 

),charPaint);

第一个参数是要绘制的字符,第二个参数绘制字符的x轴起始点,第三个参数比较复杂,重点说下前半部分

(i + 0.5) * childHeight 

表示每个字符区域高度的一办所在的y轴坐标,后半部分

(fm.ascent + fm.descent) / 2 

这个是个矫正值,如果不跟上它,绘制出来的字符会整体靠上。这里要参考字符的绘制原理,明白了后就很简单了。这里我就不在过多叙述。

最后是测试Activity的布局文件:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent" >
<com.example.demoindextextview.widget.VerticalTextView
    android:id="@+id/vertical_tv"
    android:layout_width="20dp"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:text="ABCDEFGsdfsf你好吗sdfsdklmnopqrstuvwxyz" /> 

<TextView
  android:id="@+id/content_tx"
  android:layout_gravity="center"
  android:gravity="center"
  android:layout_height="50dp"
  android:layout_width="50dp"
  android:textSize="30sp"
  android:visibility="invisible"/> 

</FrameLayout>

当字符集变化后依然很好的适应,效果图:

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Android TextView显示Html类解析的网页和图片及自定义标签用法示例

    本文实例讲述了Android TextView显示Html类解析的网页和图片及自定义标签.分享给大家供大家参考,具体如下: Android系统显示HTML网页的最佳控件为WebView,有时候为了满足特定需求,需要在TextView中显示HTML网页.图片及解析自定义标签. 1.TextView显示Html类解析的网页 CharSequence richText = Html.fromHtml("<strong>萝卜白菜的博客</strong>--<a href='

  • Android自定义TextView实现文字倾斜效果

    前言 由于Android自带的TextView控件没有提供倾斜的(我暂时没有找到),我们可以自定义控件来实现,下面首先来看我们实现的效果图. TextView文字倾斜 其实实现很简单,下面我们来看实现步骤: 1.新建一个类 LeanTextView继承TextView public class LeanTextView extends TextView { public int getmDegrees() { return mDegrees; } public void setmDegrees(

  • Android 自定义TextView实现文本内容自动调整字体大小

    最近做通讯录小屏机 联系人姓名显示--长度超过边界字体变小 /** * 自定义TextView,文本内容自动调整字体大小以适应TextView的大小 * @author yzp */ public class AutoFitTextView extends TextView { private Paint mTextPaint; private float mTextSize; public AutoFitTextView(Context context) { super(context); }

  • 解析在Android中为TextView增加自定义HTML标签的实现方法

    Android中的TextView,本身就支持部分的Html格式标签.这其中包括常用的字体大小颜色设置,文本链接等.使用起来也比较方便,只需要使用Html类转换一下即可.比如: textView.setText(Html.fromHtml(str)); 然而,有一种场合,默认支持的标签可能不够用.比如,我们需要在textView中点击某种链接,返回到应用中的某个界面,而不仅仅是网络连接,如何实现? 经过几个小时对android中的Html类源代码的研究,找到了解决办法,并且测试通过. 先看Htm

  • Android设置当TextView中的文字超过TextView的容量时用省略号代替

    有时候在ListView中显示Textview时由于长度过长而导致text会隔行显示,UI上看起来就比较的不友好. 官方提供了相关的实现单行显示的方法. 只需要下边的设置: textview.setSingleLine(); textview.setEllipsiz(TextUtils.TruncateAt.valueOf("END")); 在xml中设置如下: android:singleLine="true" android:ellipsize="en

  • Android TextView自定义数字滚动动画

    背景 在开发需求当中,当有总收益.总用户数等数字要显示时,为了更好的给用户提供展示效果,往往会想加入炫酷的数字滚动动画,使呆板平静的数字变得灵活起来,给人一种增值的直观感受. 简介 NumberRollingView是一个自定义的自带数字滚动动画的TextView,通过使用setContent(String str)方法进行数字字符串设置,传入相应的金额数字字符串(如"9686.86")或者整数数字字符串(如"968"),设置的数字必须是正数.当显示页面初始化完成的

  • Android设置TextView显示指定个数字符,超过部分显示...(省略号)的方法

    本文实例讲述了Android设置TextView显示指定个数字符,超过部分显示...(省略号)的方法.分享给大家供大家参考,具体如下: 一.问题: 今天在公司遇到一个需求:TextView设置最多显示8个字符,超过部分显示...(省略号) 二.解决方法: 网上找了很多资料,有人说分别设置TextView的android:signature="true",并且设置android:ellipsize="end";但是我试了,并没有成功,最后自己试出一种方式如下:供大家参

  • Android自定义View之继承TextView绘制背景

    本文实例为大家分享了TextView绘制背景的方法,供大家参考,具体内容如下 效果: 实现流程: 1.初始化:对画笔进行设置 mPaintIn = new Paint(); mPaintIn.setAntiAlias(true); mPaintIn.setDither(true); mPaintIn.setStyle(Paint.Style.FILL); mPaintIn.setColor(getResources().getColor(R.color.colorPrimary)); mPain

  • Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)

    一.需求: 标题可能写的不够全部,下面来看下图片,大家就明白是什么意思了.视频与票的图标跟在标题后面显示,当标题过长时icon显示到省略号-后(textview省略号显示,图标自动靠后). 二.问题解决 TextView可以通过 android:ellipsize="end" android:singleLine="true"实现单行省略, 但是当我们要是图标跟着文字后面,第一时间想到用LinearLayout的layout_weight 来做,但是做出来效果不一样

  • android开发教程之textview内容超出屏幕宽度显示省略号

    实现如下: 复制代码 代码如下: <TextView android:layout_width="fill_parent"                    android:layout_height="wrap_content"                   android:id="@+id/hello"                    android:ellipsize="end"          

  • Android开发自定义TextView省略号样式的方法

    本文实例讲述了Android开发自定义TextView省略号样式的方法.分享给大家供大家参考,具体如下: 在布局xml中设置textView的字段 android:maxLines="2"  android:ellipsize="end"字段之后,textview会自动压缩行数,并且对压缩掉的部分用...显示.如果不想用...而想用...或者... ...就需要自定义这个省略号的样式,不需要自定义控件,方法如下. 首先是布局文件 <TextView andro

  • Android自定义textview实现竖直滚动跑马灯效果

    本文实例为大家分享了Android自定义textview实现跑马灯效果的具体代码,供大家参考,具体内容如下 xml布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.c

随机推荐