【android】让Android 的EditText 显示行号(并解决行号不对齐的问题)

引言

如果想要在Android 上完成一个带有代码编写功能的EditText,那就要有高亮和行号,在这里讲解如何绘制出行号。

步骤

  1. 新建一个项目(这些步骤太基本了,不在附图),新建一个类继承自EditText。然后实现它的方法。
    public class MyEditText extends EditText {
        public MyEditText(Context context) {
            super(context);
        }

       public MyEditText(Context context, AttributeSet attrs) {
           super(context, attrs);
       }
   }

这是最基本的代码,就在这个基础上完成。

  1. 添加一个函数用来写初始化的内容, 在构造函数中调用。
    private void init() {
        setPadding(100,getPaddingTop(),getPaddingRight(),getPaddingBottom());
    }

只需要设置左边距,其他的用默认的。并且这个值应该根据某些情况改变。

  1. 重写 onDraw 方法。
   @Override
   protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      Paint lineNumberPaint=getPaint();
      int lineHeight = getLineHeight();
      for (int i=0;i<getLineCount();i++){
          int i1 = i + 1;
          canvas.drawText(i1 +"",0,(i1* lineHeight)+getPaddingTop(),lineNumberPaint);
      }
  }

也可以设置一个基础值,然后在循环中不断增加而不是用乘法。

  1. 选择 build 下面的 Make Project 或者快捷键Ctrl+F9来构建项目,这样就能够在视图上添加了。搜索我们的MyEditText ,然后添加到视图上。
  2. 现在需要对init 函数继续操作。
    设置重心。
    setGravity(Gravity.TOP|Gravity.START);
    private void init() {
        setPadding(100,getPaddingTop(),getPaddingRight(),getPaddingBottom());
        setGravity(Gravity.TOP|Gravity.START);
        setText("te\na\na\na\na\na\na\nte\na\na\na\na\n"+
          "a\na\nte\na\na\na\na\na\na\nte\na\na\na\na\na\na\n" +
         "te\na\na\na\na\na\na\nte\na\na\na\na\na\na\nte\n"+
        "a\na\na\na\na\na\nte\na\na\na\na\na\na\n" +
        "te\na\na\na\na\na\na\nte\na\na\na\na\na\na\nte\n"+
        "a\na\na\na\na\na\nte\na\na\na\na\na\na\n" +
        "te\na\na\na\na\na\na\nte\na\na\na\na\na\na\nte"+
        "\na\na\na\na\na\na\nte\na\na\na\na\na\na\n");
  }

增加的那些奇怪的部分是用来测试用的。

  1. 运行到虚拟机中效果挺好。


问题

把这个程序放到真机上运行便不行了—— 行号和内容的行对不齐。
通过读开源项目和源码,发现一个getLineTopgetLineBottom 函数,控制行号位置不再通过乘法或者加法。

/**
* Return the vertical position of the top of the specified line
* (0…getLineCount()).
* 返回指定行的顶部的垂直位置
* If the specified line is equal to the line count, returns the
* bottom of the last line.
* 如果指定的行等于行号,返回最后一行的底部
*/

    /**
     * Return the vertical position of the bottom of the specified line.
     * 返回指定行的底部的垂直位置
     */
    public final int getLineBottom(int line) {
        return getLineTop(line + 1);
    }
    private int getCurrentLine() {//获取光标所在行
        int selectionStart = getSelectionStart();
        Layout layout = getLayout();
        if (selectionStart != -1 && layout != null) {
            return layout.getLineForOffset(selectionStart);
        }
        return -1;
    }
    Paint lineHeightPaint = new Paint();
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        lineHeightPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        lineHeightPaint.setColor(Color.argb(100, 90, 164, 161));
        int currentCursorPositionLine = getCurrentLine();
        int lineTop = getLayout().getLineTop(currentCursorPositionLine);
        int lineCount1 = getLineCount();
        int paddingTop = getPaddingTop();
        int lineBottom1 = getLayout().getLineBottom(currentCursorPositionLine + 1);
        canvas.drawRect(0, lineTop + paddingTop, getWidth(), lineBottom1 - paddingTop, lineHeightPaint);//用来高亮当前选中行
        Paint lineNumberPaint=getPaint();
        for (int i=0;i<lineCount1;i++){
            int i1 = i + 1;
            int lineBottom = getLayout().getLineBottom(i);
            canvas.drawText(Integer.toString(i1), 0, lineBottom + paddingTop, lineNumberPaint);
        }
    }

现在点击EditText 看高亮的行和行号是不是对齐的了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章