【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 看高亮的行和行號是不是對齊的了。

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