Android学习小Demo(11)一个显示行线的自定义EditText
来源:互联网 发布:webstorm js 格式化 编辑:程序博客网 时间:2024/06/02 04:35
今天在处理一个EditText的时候,想着把EditText做成像一本作业本上的纸一样,每一行都可以由线条隔开,具体效果如下:
1)最开始的思路
一开始的想法是很简单的,找出每一行的高度,然后一行一行地画线不就好了吗,代码如下:
viewHeight = getMeasuredHeight(); viewWidth = getMeasuredWidth(); lineHeight = getLineHeight(); int maxLines = viewHeight / lineHeight + 1; int i = 0; int currentLineHeight = 0;while(i < maxLines){currentLineHeight += lineHeight;canvas.drawLine(0, currentLineHeight, viewWidth, currentLineHeight, mPaint);i++;}但是出来的效果一看,高度很明显不够,如下:
看起来好像是高度的问题,那就每一行的高度都加一点呗,再试试:
lineHeight = getLineHeight() + 5;再来看一下效果,前面几行好像效果不错呀,但是到后面又挤在一起了,我估计这里面的原因应该是getLineHeight返回来的值不是标准的,而是随着内容的变化而不同,看一下它的函数说明,如下:
/** * @return the height of one standard line in pixels. Note that markup * within the text can cause individual lines to be taller or shorter * than this height, and the layout may contain additional first- * or last-line padding. */ public int getLineHeight() { return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd); }果然是这样,那么通过这个getLineHeight来表示每一行的高度就不可行了。
在android提供的sample里面,有一个是NotePad的小demo,在里面它实现了为EditText里面的每一行添加一条下划线,其代码如下:
public static class LinedEditText extends EditText { ... @Override protected void onDraw(Canvas canvas) { int count = getLineCount(); Rect r = mRect; Paint paint = mPaint; for (int i = 0; i < count; i++) { int baseline = getLineBounds(i, r); canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint); } super.onDraw(canvas); } }好,我们就用它这个来试试,看效果
不错哦!但是发现一个问题,后面没有字符的它就不划线了,这是因为它划线的基础在于getLineCount这个函数,定义如下:
/** * Return the number of lines of text, or 0 if the internal Layout has not * been built. */ public int getLineCount() { return mLayout != null ? mLayout.getLineCount() : 0; }就是说,它返回来的值是跟内容有关的的,而getLineBounds的取值则是基于getLineCount的,定义如下(看第一句注释):
/** * Return the baseline for the specified line (0...getLineCount() - 1) * If bounds is not null, return the top, left, right, bottom extents * of the specified line in it. If the internal Layout has not been built, * return 0 and set bounds to (0, 0, 0, 0) * @param line which line to examine (0..getLineCount() - 1) * @param bounds Optional. If not null, it returns the extent of the line * @return the Y-coordinate of the baseline */ public int getLineBounds(int line, Rect bounds)所以,只有有内容的行才会画下划线,可是我们的目标是没有内容也想划一条线,如何是好呢?
我的想法一样很简单,在屏幕上显示的线条其实是有限的,那么就分成两部分,前面一部分是有内容的,就拿上面NotePad这种办法画,如果线条的数目已填满这个区域了(其实是达到预先定义的最大数目了),则不必自己再去画,反之,如果还差几样没有画,那么就根据前面已经画出来的平均高度,把剩下的几条线也给画上,因为当输入内容的时候,EditText其实是一直在刷新的,所以自然而然,新添加的内容的线条也是应用上面NotePad那种方法来画的,所以画出来的线也是符合要求的。这个自定义EditText的完整代码如下:
package com.lms.todo.views;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.util.AttributeSet;import android.widget.EditText;/** * @author Linmiansheng */public class CustomEditText extends EditText {//private static final String TAG = "com.lms.todo.views.CustomEditText";private Rect mRect; private Paint mPaint; private final int padding = 10; private int lineHeight; private int viewHeight,viewWidth; public CustomEditText(Context context) { this(context, null); } public CustomEditText(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs); } private void init(Context context, AttributeSet attrs) { mRect = new Rect(); mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.BLACK); mPaint.setAntiAlias(true); setFocusable(true); setFocusableInTouchMode(true); } @Override protected void onDraw(Canvas canvas) { int count = getLineCount(); Rect r = mRect; Paint paint = mPaint; int lineHeight = 0; int i = 0; while (i < count) {lineHeight = getLineBounds(i, r);canvas.drawLine(r.left, lineHeight + padding, r.right, lineHeight + padding,paint);i++;}int maxLines = 15;int avgHeight = lineHeight / count;int currentLineHeight = lineHeight;while(i < maxLines){currentLineHeight = currentLineHeight + avgHeight + padding;canvas.drawLine(r.left, currentLineHeight, r.right, currentLineHeight, paint);i++;} super.onDraw(canvas); }}
不过有一点要注意的就是,这个padding的设置,也就是每一行的高度,其实跟我们在应用的时候设置的字体大小也是有一定的关系的,所以,真正应用的话,可能要去调一下。
在xml布局中的使用如下:
<com.lms.todo.views.CustomEditText android:id="@+id/etContent" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_weight="8" android:background="#00000000" android:gravity="top" android:inputType="textMultiLine" android:padding="5dip" android:textSize="20sp" />
结束。
1 0
- Android学习小Demo(11)一个显示行线的自定义EditText
- Android学习小Demo(15)一个自定义AlertDialog的实现
- Android 自定义View(1) -- 一个小Demo
- Android学习小demo(1)自定义View
- Android学习小demo(2)自定义ViewGroup
- Android学习小Demo(10)ToDoList的改进版之ViewPager显示多个图片
- Android 带删除图标的EditText清除功能小Demo
- Android学习小Demo(9)一个To Do List的实现
- Android自定义View研究(一) -- 一个小Demo
- Android自定义View研究(一) -- 一个小Demo
- 【Android】Android开发点击查看手机电量的小功能。学习广播的一个小技能小Demo
- Android学习中关于SQLite的一个小Demo(数据库的创建、数据的增删查改)
- Android学习小Demo(7)SharedPreference的使用
- Android学习小Demo(8)SQLiteDatabase的使用
- Android学习小Demo(10)ToDoList的加强版
- Android学习小Demo(20)关于Fragment的应用
- Android学习小Demo(21)ListView的联动选择
- 自定义一个可以自动循环显示图片的Demo
- 移植sqlite3.8到arm开发板过程
- Android Handler笔记
- android 隐藏键盘
- MDM(Afaria)设置iPad进入“引导模式”后,如何退出“引导模式”
- poj 2407
- Android学习小Demo(11)一个显示行线的自定义EditText
- sysctl命令详解
- flex(air for android )操作menu
- How to Install WineHQ 1.5.27 on Fedora, CentOS and RHEL Linux Distributions
- 逆天的骨骼动画工具 Spine 把2D画皮3D网格化。
- UVA 10125 (14.3.6)
- 数据挖掘过程
- 【ORACLE RAC】root.sh原理,ocr管理
- tcp_keepalive的设置