1. 程式人生 > >Android EditText終極美化------帶行號、下劃線、彈性效果、游標美化

Android EditText終極美化------帶行號、下劃線、彈性效果、游標美化

不多說,直接上程式碼:

需要說明的是,涉及到效率問題主要是在setText()和setPadding(),該方法用於調整行號的寬度,需要先知道最大行號數字的長度。所以需要先setText()把內容顯示在EditText中,再通過getLineCount()獲取最大行號,然後再setPadding(),這樣的效率比較低,對於大量的資料可能會出現ANR。

解決方案就是把最大行號和內容一起儲存起來,下次讀取內容的時候先通過最大行號setPadding(),再setText()。

NoteEditText.java

public class NoteEditText extends EditText {

    private Context context;
    private boolean initialized;
    // 畫筆 用來畫下劃線
    private Paint paint;
    private Paint mNumPaint;
    private Paint mRectPaint;
    private int mNumberLength;
    private float mTextSize; // sp

    private ScrollView mScrollView;

    public static final String KEY_TEXT_SIZE = "textSize";
    private String KEY_NUMBER_LENGTH = "_numberLength";
    public static final String KEY_SHOW_LINE = "showLine";
    public static final String KEY_SHOW_LINE_NUMBER = "showLineNumber";

    public static final float DEFAULT_VALUE_TEXT_SIZE = 20;
    public static final boolean DEFAULT_VALUE_SHOW_LINE = true;
    public static final boolean DEFAULT_VALUE_SHOW_LINE_NUMBER = false;
    private boolean showLine;
    private boolean showLineNumber;

    private int mPaddingLeft;

    private static final int LINE_OFFSET = 50;

    float displayPaddingLeft;

    public NoteEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
        setTextCursor();
    }

    // 自定義游標
    private void setTextCursor() {
        try {
            Method createEditorIfNeeded = ReflectionUtils.getMethod(
                    "android.widget.TextView", "createEditorIfNeeded", null);
            if (createEditorIfNeeded != null) {
                createEditorIfNeeded.setAccessible(true);
                createEditorIfNeeded.invoke(this, new Object[0]);
                Field editor = ReflectionUtils.getField(
                        "android.widget.TextView", "mEditor");
                if (editor != null) {
                    editor.setAccessible(true);
                    Field cursorDrawable = ReflectionUtils.getField(
                            "android.widget.Editor", "mCursorDrawable");
                    if (cursorDrawable != null) {
                        cursorDrawable.setAccessible(true);
                        Array.set(cursorDrawable.get(editor.get(this)), 0,
                                new LineSpaceCursorDrawable(context, this));
                        Array.set(cursorDrawable.get(editor.get(this)), 1,
                                new LineSpaceCursorDrawable(context, this));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void init() {
        showLine = Cache.read_Boolean(KEY_SHOW_LINE, DEFAULT_VALUE_SHOW_LINE);
        if (showLine) {
            paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(DisplayUtils.dip2px(context, 0.5f));
            paint.setColor(context.getResources().getColor(
                    R.color.note_edittext_line_color));
            // 開啟抗鋸齒 較耗記憶體
            paint.setAntiAlias(true);
        }
        showLineNumber = Cache.read_Boolean(KEY_SHOW_LINE_NUMBER,
                DEFAULT_VALUE_SHOW_LINE_NUMBER);
        if (showLineNumber) {
            mNumPaint = new Paint();
            mNumPaint.setStyle(Paint.Style.FILL);
            mNumPaint.setColor(context.getResources().getColor(
                    R.color.note_edittext_line_number_color));
            // 開啟抗鋸齒 較耗記憶體
            mNumPaint.setAntiAlias(true);

            mPaddingLeft = getPaddingLeft();

            mRectPaint = new Paint();
            mRectPaint.setStyle(Paint.Style.FILL);
            mRectPaint.setColor(context.getResources().getColor(
                    R.color.note_edittext_line_number_rect_color));// Color.rgb(153,
                                                                   // 148,
                                                                   // 252));
        }
        displayPaddingLeft = DisplayUtils.dip2px(context, 5);
        setTextSize(Cache.read_float(KEY_TEXT_SIZE, DEFAULT_VALUE_TEXT_SIZE));
    }

    // 新增彈性效果
    public void setScrollView(ScrollView scrollView) {
        mScrollView = scrollView;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        try {
            if (!showLine && !showLineNumber)
                return;

            if (!initialized)
                return;

            // 得到總行數
            int lineCount = getLineCount();
            // 得到每行的高度
            int lineHeight = getLineHeight();

            int lineStart = 0;

            if (mScrollView != null) {
                lineStart = (mScrollView.getScrollY() - getPaddingTop())
                        / lineHeight - LINE_OFFSET;
                lineStart = lineStart >= 0 ? lineStart : 0;
            }
            int lineEnd = lineStart
                    + ScreenInfo.getInstance().getHeightPixels() / lineHeight
                    + LINE_OFFSET * 2;

            if (showLineNumber) {

                int numberLength = getNumberLength(lineCount);
                numberLength = numberLength > 2 ? numberLength : 2;
                if (numberLength != mNumberLength) {
                    Logger.d("numberLength != mNumberLength lineCount:"
                            + lineCount + " getVisibility:"
                            + this.getVisibility());
                    mNumberLength = numberLength;
                    Cache.write_int(KEY_NUMBER_LENGTH, mNumberLength);
                    adjustPadding();
                }

                // 繪製行號背景
                canvas.drawRect(new Rect(0, mScrollView.getScrollY()
                        - (int) DisplayUtils.dip2px(context, 600), mPaddingLeft
                        - (int) displayPaddingLeft, mScrollView.getScrollY()
                        + ScreenInfo.getInstance().getHeightPixels()
                        + (int) DisplayUtils.dip2px(context, 600)), mRectPaint);

                float textWidth = getNumberTextWidth(mNumPaint);

                for (int i = lineStart; i < lineEnd; i++) {
                    int x = (int) (mPaddingLeft - displayPaddingLeft
                            - DisplayUtils.dip2px(context, 15) / 2 - getNumberLength(i + 1)
                            * textWidth);
                    int y = ((i + 1) * getLineHeight()) - (getLineHeight() / 8);
                    canvas.drawText(String.valueOf(i + 1), x, y, mNumPaint);
                }
            }

            if (showLine) {
                // 根據行數迴圈畫線
                for (int i = lineStart; i < lineEnd; i++) {
                    int lineY = (i + 1) * lineHeight;
                    canvas.drawLine(
                            0,
                            this.getPaddingTop()
                                    - ViewUtils.getLineSpacingExtra(context,
                                            this) / 2 + lineY,
                            this.getWidth(),
                            this.getPaddingTop()
                                    - ViewUtils.getLineSpacingExtra(context,
                                            this) / 2 + lineY, paint);
                }
            }
        } finally {
            super.onDraw(canvas);
        }

    }

    // 調整行號的寬度
    private void adjustPadding() {
        mPaddingLeft = (int) (DisplayUtils.dip2px(context, 15)
                + displayPaddingLeft + mNumberLength
                * getNumberTextWidth(mNumPaint));
        setPadding(mPaddingLeft, getPaddingTop(), getPaddingRight(),
                getPaddingBottom());
    }

    public void initText(CharSequence text) {
        if (!TextUtils.isEmpty(text))
            setText(text);
        initialized = true;
    }

    @Override
    public void setTextSize(float size) {
        Logger.d("mTextSize" + mTextSize);
        Logger.d("mTextSize size:" + size);
        Logger.d("mTextSize" + Calculator.equals(size, mTextSize));
        if (!Calculator.equals(size, mTextSize)) {
            super.setTextSize(size);
            mTextSize = size;
            Logger.d("mTextSize" + mTextSize);
            if (showLineNumber) {
                mNumPaint.setTextSize(getTextSize());
                adjustPadding();
            }
            Cache.write_float(KEY_TEXT_SIZE, mTextSize);
        }
    }

    public float getTextSizeSP() {
        return mTextSize;
    }

    public static float getNumberTextWidth(Paint paint) {
        float[] widths = new float[1];
        paint.getTextWidths("0", widths);
        return widths[0];
    }

    public void initNumberLength(String filePath) {
        if (showLineNumber) {
            KEY_NUMBER_LENGTH = filePath + KEY_NUMBER_LENGTH;
            Logger.d("KEY_NUMBER_LENGTH:" + KEY_NUMBER_LENGTH);
            mNumberLength = Cache.read_int(KEY_NUMBER_LENGTH,
                    getNumberLength(getLineCount()));
            adjustPadding();
        }
    }

    public static int getTextWidth(Paint paint, String str) {
        int iRet = 0;
        if (str != null && str.length() > 0) {
            int len = str.length();
            float[] widths = new float[len];
            paint.getTextWidths(str, widths);
            for (int j = 0; j < len; j++) {
                iRet += (int) Math.ceil(widths[j]);
            }
        }
        return iRet;
    }

    private int getNumberLength(int n) {
        int length = 0;
        while (n > 0) {
            n = n / 10;
            length++;
        }
        return length;
    }

}
自定義游標:
LineSpaceCursorDrawable.java
public class LineSpaceCursorDrawable extends ShapeDrawable {

    private Context context;
    private EditText view;

    public LineSpaceCursorDrawable(Context context, EditText view) {
        Logger.d("LineSpaceCursorDrawable new");
        this.context = context;
        setDither(false);
        Resources res = view.getResources();
        getPaint().setColor(res.getColor(ThemeManager.getInstance().background_color));//R.color.note_edittext_cursor_color));
        setIntrinsicWidth((int)DisplayUtils.dip2px(context, 2));//res.getDimensionPixelSize(R.dimen.detail_notes_text_cursor_width));
        this.view = view;
    }

    public void setBounds(int left, int top, int right, int bottom) {
        Logger.d("LineSpaceCursorDrawable setBounds");

        Editable s = view.getText();
        ImageSpan[] imageSpans = s.getSpans(0, s.length(),
                ImageSpan.class);
        int selectionStart = view.getSelectionStart();
        for (ImageSpan span : imageSpans) {
            int start = s.getSpanStart(span);
            int end = s.getSpanEnd(span);
            if (selectionStart >= start && selectionStart <= end)
            {
                super.setBounds(left, top, right, top - 1);
                return;
            }
        }
        super.setBounds(left, top, right, top + view.getLineHeight() - (int)ViewUtils.getLineSpacingExtra(context, view));

    }
}
ViewUtils.java
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public static float getLineSpacingExtra(Context context, TextView view){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            return view.getLineSpacingExtra();
        }
        else{
            return DisplayUtils.dip2px(context, 8);
        }
    }
DisplayUtils.java
    /** 
     * 將dip或dp值轉換為px值,保證尺寸大小不變 
     *  
     * @param dipValue 
     * @param scale 
     *            (DisplayMetrics類中屬性density) 
     * @return 
     */  
    public static float dip2px(Context context, float dipValue) {  
        float scale = context.getResources().getDisplayMetrics().density;  
        return dipValue * scale + 0.5f;  
    }
ScreenInfo.java
public class ScreenInfo {
    private int widthPixels;
    private int heightPixels;
    
    private static ScreenInfo instance;

    private ScreenInfo(Activity context) {
        DisplayMetrics dm = new DisplayMetrics();

        context.getWindowManager().getDefaultDisplay().getMetrics(dm);
        this.widthPixels = dm.widthPixels;
        this.heightPixels = dm.heightPixels;
    }
    
    public static void createInstance(Activity context){
        if(instance == null)
            instance = new ScreenInfo(context);
    }
    
    public static ScreenInfo getInstance(){
        return instance;
    }
    
    public static ScreenInfo getInstance(Activity context){
        if(instance == null)
            instance = new ScreenInfo(context);
        return instance;
    }

    /**
     * @return the number of pixel in the width of the screen.
     */
    public int getWidthPixels() {
        return widthPixels;
    }

    /**
     * @return the number of pixel in the height of the screen.
     */
    public int getHeightPixels() {
        return heightPixels;
    }
    
    public String getSize() {
        return widthPixels + "×" + heightPixels;
    }
}
ReflectionUtils.java
public class ReflectionUtils {
    private static final String TAG = "ReflectionUtils";

    public static boolean hasMethod(String className, String method, Class[] params) {
        try {
            Class<?> targetClass = Class.forName(className);
            if (params != null) {
                targetClass.getMethod(method, params);
                return true;
            }
            targetClass.getMethod(method, new Class[0]);
            return true;
        } catch (SecurityException e) {
            e.printStackTrace();
            return false;
        } catch (NoSuchMethodException e2) {
            e2.printStackTrace();
            return false;
        } catch (IllegalArgumentException e3) {
            e3.printStackTrace();
            return false;
        } catch (ClassNotFoundException e4) {
            e4.printStackTrace();
            return false;
        }
    }

    public static Method getMethod(String className, String method, Class[] params) {
        try {
            return Class.forName(className).getDeclaredMethod(method, params);
        } catch (SecurityException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchMethodException e2) {
            e2.printStackTrace();
            return null;
        } catch (IllegalArgumentException e3) {
            e3.printStackTrace();
            return null;
        } catch (ClassNotFoundException e4) {
            e4.printStackTrace();
            return null;
        }
    }

    public static Field getField(String className, String name) {
        try {
            return Class.forName(className).getDeclaredField(name);
        } catch (SecurityException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchFieldException e2) {
            e2.printStackTrace();
            return null;
        } catch (IllegalArgumentException e3) {
            e3.printStackTrace();
            return null;
        } catch (ClassNotFoundException e4) {
            e4.printStackTrace();
            return null;
        }
    }
}

NoteEditText的使用:

            <com.xxx.ElasticScrollView
            	android:id="@+id/scrollview"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:fastScrollEnabled="true"
                android:fillViewport="true" >
                <com.xxx.NoteEditText
                    android:id="@+id/content"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:background="@null"
                    android:fadingEdge="vertical"
                    android:gravity="top"
                    android:paddingLeft="15dp"
                    android:paddingRight="15dp"
                    android:paddingTop="8dp"
                    android:paddingBottom="8dp"
                    android:scrollbars="vertical"
                    android:lineSpacingExtra="8dp"
                    android:text="" />
            </com.xxx.ElasticScrollView>


ElasticScrollView.java
/**
 * 有彈性的ScrollView
 * 實現下拉彈回和上拉彈回
 * @date Feb 13, 2014 6:11:33 PM
 */
public class ElasticScrollView extends ScrollView {
	
	private static final String TAG = "ElasticScrollView";
	
	//移動因子, 是一個百分比, 比如手指移動了100px, 那麼View就只移動50px
	//目的是達到一個延遲的效果
	private static final float MOVE_FACTOR = 0.2f;
	
	//鬆開手指後, 介面回到正常位置需要的動畫時間
	private static final int ANIM_TIME = 300;
	
	//ScrollView的子View, 也是ScrollView的唯一一個子View
	private View contentView; 
	
	//手指按下時的Y值, 用於在移動時計算移動距離
	//如果按下時不能上拉和下拉, 會在手指移動時更新為當前手指的Y值
	private float startY;
	
	//用於記錄正常的佈局位置
	private Rect originalRect = new Rect();
	
	//手指按下時記錄是否可以繼續下拉
	private boolean canPullDown = false;
	
	//手指按下時記錄是否可以繼續上拉
	private boolean canPullUp = false;
	
	//在手指滑動的過程中記錄是否移動了佈局
	private boolean isMoved = false;

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

	@Override
	protected void onFinishInflate() {
		if (getChildCount() > 0) {
			contentView = getChildAt(0);
		}
	}
	
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		
		if(contentView == null) return;

		//ScrollView中的唯一子控制元件的位置資訊, 這個位置資訊在整個控制元件的生命週期中保持不變
		originalRect.set(contentView.getLeft(), contentView.getTop(), contentView
				.getRight(), contentView.getBottom());
	}
	
	/**
	 * 在該方法中獲取ScrollView中的唯一子控制元件的位置資訊
	 * 這個位置資訊在整個控制元件的生命週期中保持不變
	 */
	
	/**
	 * 在觸控事件中, 處理上拉和下拉的邏輯
	 */
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		
		if (contentView == null) {
			return super.dispatchTouchEvent(ev);
		}

		int action = ev.getAction();
		
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			
			//判斷是否可以上拉和下拉
			canPullDown = isCanPullDown();
			canPullUp = isCanPullUp();
			
			//記錄按下時的Y值
			startY = ev.getY();
			break;
			
		case MotionEvent.ACTION_UP:
			
			if(!isMoved) break;  //如果沒有移動佈局, 則跳過執行
			
			// 開啟動畫
			TranslateAnimation anim = new TranslateAnimation(0, 0, contentView.getTop(),
					originalRect.top);
			anim.setDuration(ANIM_TIME);
			
			contentView.startAnimation(anim);
			
			// 設定回到正常的佈局位置
			contentView.layout(originalRect.left, originalRect.top, 
					originalRect.right, originalRect.bottom);
			
			//將標誌位設回false
			canPullDown = false;
			canPullUp = false;
			isMoved = false;
			
			break;
		case MotionEvent.ACTION_MOVE:
			
			//在移動的過程中, 既沒有滾動到可以上拉的程度, 也沒有滾動到可以下拉的程度
			if(!canPullDown && !canPullUp) {
				startY = ev.getY();
				canPullDown = isCanPullDown();
				canPullUp = isCanPullUp();
				
				break;
			}
			
			//計算手指移動的距離
			float nowY = ev.getY();
			int deltaY = (int) (nowY - startY);
			
			//是否應該移動佈局
			boolean shouldMove = 
					(canPullDown && deltaY > 0)    //可以下拉, 並且手指向下移動
					|| (canPullUp && deltaY< 0)    //可以上拉, 並且手指向上移動
					|| (canPullUp && canPullDown); //既可以上拉也可以下拉(這種情況出現在ScrollView包裹的控制元件比ScrollView還小)
			
			if(shouldMove){
				
				//計算偏移量
				int offset = (int)(deltaY * MOVE_FACTOR);
				
				//隨著手指的移動而移動佈局
				contentView.layout(originalRect.left, originalRect.top + offset,
						originalRect.right, originalRect.bottom + offset);
				
				isMoved = true;  //記錄移動了佈局
			}
			
			break;
		default:
			break;
		}

		return super.dispatchTouchEvent(ev);
	}
	

	/**
	 * 判斷是否滾動到頂部
	 */
	private boolean isCanPullDown() {
		return getScrollY() == 0 || 
				contentView.getHeight() < getHeight() + getScrollY();
	}
	
	/**
	 * 判斷是否滾動到底部
	 */
	private boolean isCanPullUp() {
		return  contentView.getHeight() <= getHeight() + getScrollY();
	}

}

((NoteEditText) editText).setScrollView((ScrollView) view
                .findViewById(R.id.scrollview));

效果展示,順便打個廣告:



相關推薦

Android EditText終極美化------劃線彈性效果游標美化

不多說,直接上程式碼: 需要說明的是,涉及到效率問題主要是在setText()和setPadding(),該方法用於調整行號的寬度,需要先知道最大行號數字的長度。所以需要先setText()把內容顯示在EditText中,再通過getLineCount()獲取最大行號,然後

分割槽函式Partition Byrow_number()排序rank()的用法詳解

partition by關鍵字是分析性函式的一部分,它和聚合函式不同的地方在於它能返回一個分組中的多條記錄,而聚合函式一般只有一條反映統計值的記錄,partition by用於給結果集分組,如果沒有指定那麼它把整個結果集作為一個分組,分割槽函式一般與排名函式一起使用。 準備測試資料:

一句話實現Mysql查詢結果

mys span sele font spa lec sql 行號 ont SELECT @rowno:=@rowno + 1 AS rowno,a.* FROM tableName a,(SELECT @rowno:=0) b一句話實現Mysql查詢結果帶行號

的log日誌提示

                                                                    HELLO ,I MISS YOU! 使用環境:               需要在列印log的同時,提示在專案類之中的哪一行。

Android EditText 自定義刪除按鈕

EditText裡面帶刪除按鈕在各種App裡面已經很常見了,如下: 所需的圖片資源: 下面直接貼上全部程式碼: public class ClearEditText extends EditText implements OnFocu

android採用MVP完整漫畫APP釘釘地圖效果功能完善的音樂播放器仿QQ動態登入效果觸手app主頁等原始碼

Android精選原始碼 Android優質部落格 應用不相容的常見原因使用了系統的 ClassLoader 載入 org.apache.http. 的庫Android M 就已經開始移除對 Apache HTTP client 的

UILable顯示不同的字型顏色字型大小間距縮排劃線等屬性(NSMutableAttributedString)

案例1:修改文字字型大小、顏色屬性 比如文字展示為姓名和性別,但是我們不能排除姓名會很長,所以此刻的lable寬度我們就不能寫死,換句話說lable的寬度根據文字的內容來定 我經常用兩種方式解決: 2.就是使用NSMutableAttributedString屬性

PHP正則匹配6到16位字符組合(且只能為數字字母劃線)

lin asd fun 整合 bsp pass www. 正則 -m php正則匹配6到16位的字符串。 只允許包含數字、字母、下劃線組成的6到16位字符,符合返回ture,否則返回false。 解答: 6到16位,正則可以這樣寫:{6,16}。 任意的字符6到16位的正則

js物件屬性駝峰式命名(數字)轉劃線命名

將類似於 info 格式轉化為 info2  var info = { id: 1, id1: 2, userName1: '劉玄德', userName2: '劉玄德', userName3: '大哥',

RichEditor——一款基於RecyclerView實現的富文字編輯器實現方案(支援圖文轉義生成MarkDown粗體斜體劃線刪除線超連結標題等)

前言 對於富文字編輯器的實現,首先我們肯定會想到實現的編輯器需要支援的幾個必要特性: 1.涉及大量文字,圖片,文字樣式的展示與編輯。 2.涉及極其複雜的使用者互動。 目前Github上我所瞭解的富文字編輯器基本上實現方式基於兩種: * 1.基於WebView

java驗證,”支援6-20個字母數字劃線或減號,以字母開頭“這個的正則表示式怎麼寫?

轉自:https://yq.aliyun.com/wenzhang/show_96854 問題描述 java驗證,”支援6-20個字母、數字、下劃線或減號,以字母開頭“這個的正則表示式怎麼寫? 驗證”支援6-20個字母、數字、下劃線或減號,以字母開頭“的正則表示式

大家一起學python-day4-統計數字字母劃線的數量

#第一種 #直接通過範圍查詢 shuzi =0 zhimu =0 xiahuaxian =0 qita =0 a = 'dsadasd34sda3dfsf_gfd???' b = len(a) for i in range(0,b): if a[i]>='1' and a[i]

專業乾貨!想強調重點該用粗體劃線還是斜體?

你以為的加粗很多是假粗體;下劃線只是打字機時代的產物,如今根本不能用;中文沒有斜體…. 以上僅僅是@justfont 這篇好文的眾多亮點之一,這不僅是一堂生動的字型科普課,也附上了強調文字的實用方法。只要你需要排版,這篇文章就不能放過,都是基礎功呀。 計算機輔助的設計中,一般人可以輕易的凸顯任何內文。只要透

iOS NSMutableAttributedString 實現富文字(不同顏色字型劃線等)

//    1> NSFontAttributeName(字型) //    該屬性所對應的值是一個 UIFont 物件。該屬性用於改變一段文字的字型。如果不指定該屬性,則預設為12-point Helvetica(Neue)。 //     //    2> NSParagraphSt

Android開發技巧——去掉TextView中autolink的劃線

我們知道,在佈局檔案中設定textview的autolink及其型別,這時textivew上會顯示link的顏色,並且文字下面會有一條下劃線,表示可以點選。而在我們在點選textview時,應用將根據我們所設定的型別跳轉到對應的介面。但是有時,我們因介面需求,需要去掉介面上

使用NSMutableAttributedString 實現富文字(不同顏色字型劃線等)

開發中,常常會有一段文字顯示不同的顏色和字型,或者給某幾個文字加刪除線或下劃線的需求。NSMuttableAttstring(帶屬性的字串),上面的一些需求都可以很簡便的實現。 1.例項化方法有兩種: 使用字串來初始化 ①:- (id)initWithSt

WPS文字設定奇偶頁首劃線的方法步驟

這個問題困擾了我一天,問了無數人都不會,最後還是自己無意間網上查到一個點給了我靈感。 本文將解決以下問題: 1、頁首新增下劃線、設定下劃線的粗細? 2、如何將奇偶頁的頁首設定成不一樣的格式,例如: 單

正則表示式——判斷字串組成,第一個必須是字母,後面可以是字母數字劃線,總長度為5-20

//判斷字串是否是這樣組成的,第一個必須是字母,後面可以是字母、數字、下劃線,總長度為5-20 var c = /^[a-zA-Z]\w{4,19}$/; // /是轉義 ^ 是開頭 [

TextView測量文字長度加粗刪除線劃線

測量文字的長度 一定要記著post()與主執行緒直接獲取的區別,View的dispatchAttachedToWindow()方法呼叫才會執行runnable中的action,而這個方法設計Android底層UI邏輯處理。反正記住,post方法會在View的p

密碼6-20位,只允許字母數字劃線其中兩項

最近專案的註冊模組優化,密碼的檢驗規則加強了,支援數字、字母、符號6-20位,必須包含其中至少兩種。開始用Google一頓狂search,然而並沒有找到合適的正則,本來都準備放棄正則,自己手寫判斷條件了。今天找一個類似的,然後自己試著改了下,居然成功了(此處容我