欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)梯形TextView效果

 更新時間:2021年05月27日 09:39:08   作者:不會飛的小豬  
TextView(文本框),用于顯示文本的一個控件,Android開發(fā)中經(jīng)常使用,本文講述如何實現(xiàn)一個梯形的TextView

效果圖:

自定義代碼實現(xiàn)邏輯:

public class LadderTextView extends android.support.v7.widget.AppCompatTextView {
    private static final String TAG = "LadderView";
    private Path linePath;
    private Paint paint, textPaint;
    private int width, height;
    private float strokeWidth = 2;
    private Region mRegion;
    private String textContent;
    private int lineOffset = 0;//劃線的偏移量
    private int textOffset = 0;//文本的偏移量
    private float offsetScale = 1;//梯高與(梯頂與梯底)之差的比例(梯底比梯頂長)
    private boolean isLeft = true;//分為左和右兩種斜角梯形模式
    private boolean isSelected = false;//是否是選定
    private int selectedColor = Color.BLACK;

    public LadderTextView(Context context) {
        super(context);
        init();
    }

    public LadderTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttributes(context, attrs);
        init();
    }


    public LadderTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttributes(context, attrs);
        init();
    }

    private void initAttributes(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LadderTextView);
        textContent = typedArray.getString(R.styleable.LadderTextView_textContent);
        offsetScale = typedArray.getFloat(R.styleable.LadderTextView_offsetScale, 0.5f);
        isLeft = typedArray.getBoolean(R.styleable.LadderTextView_isLeft, true);
        isSelected = typedArray.getBoolean(R.styleable.LadderTextView_isSelected, true);
        selectedColor = typedArray.getColor(R.styleable.LadderTextView_selectedColor, Color.GREEN);
        strokeWidth = typedArray.getDimension(R.styleable.LadderTextView_strokeWidth, 1);
        typedArray.recycle();
    }

    private void init() {
        Log.v(TAG, "init");
        mRegion = new Region();
        paint = new Paint();
        textPaint = new Paint();
        linePath = new Path();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(dp2px(getContext(), strokeWidth));
        paint.setColor(selectedColor);
        paint.setStyle(isSelected ? Paint.Style.FILL_AND_STROKE : Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);

        textPaint.setAntiAlias(true);
        textPaint.setTextSize(getTextSize());//傳遞TextSize(px)
        textPaint.setColor(isSelected ? Color.WHITE : selectedColor);
        setText("");//去除掉原有的Text內(nèi)容
        lineOffset = dp2px(getContext(), strokeWidth) / 2;
        textOffset = (int) (getTextSize() / 2) + getBaseline() * 2;
        Log.v(TAG, "lineOffset textOffset ->" + lineOffset + " " + textOffset);
    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getWidth();
        height = getHeight();
        Log.v(TAG, "width height->" + width + " " + height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.v(TAG, "onDraw");
        if (isLeft) {
            linePath.moveTo(0 + lineOffset, 0 + lineOffset);
            linePath.lineTo(width, 0 + lineOffset);
            linePath.lineTo((int) (width - offsetScale * height), height - lineOffset);
            linePath.lineTo(0 + lineOffset, height - lineOffset);
            linePath.close();
            setTextAlignment(TEXT_ALIGNMENT_TEXT_START);
            canvas.drawPath(linePath, paint);
            canvas.drawText(textContent == null ? "" : textContent,
                    getPaddingStart() + lineOffset,
                    height / 2 + textOffset, textPaint);
        } else {
            linePath.moveTo(0 + lineOffset + offsetScale * height, 0 + lineOffset);
            linePath.lineTo(width - lineOffset, 0 + lineOffset);
            linePath.lineTo(width - lineOffset, height - lineOffset);
            linePath.lineTo(0, height - lineOffset);
            linePath.close();
            setTextAlignment(TEXT_ALIGNMENT_TEXT_END);
            canvas.drawPath(linePath, paint);
            canvas.drawText(textContent == null ? "" : textContent,
                    getWidth() - lineOffset - getPaddingEnd() - getDrawTextWidth(textPaint, textContent),
                    height / 2 + textOffset, textPaint);
        }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (!isInRegion(event)) {//點擊的點的位置不在范圍內(nèi)則不響應
                return false;
            }
        }
        return super.dispatchTouchEvent(event);
    }

    /**
     * 判斷點擊的位置是否在要求的范圍內(nèi)
     * @param event
     * @return
     */
    public boolean isInRegion(MotionEvent event) {
        RectF rectF = new RectF();
        linePath.computeBounds(rectF, true);
        mRegion.setPath(linePath, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));
        return mRegion.contains((int) event.getX(), (int) event.getY());
    }

    /**
     * 獲取要畫的字符串的寬度
     *
     * @param paint
     * @param textContent
     * @return
     */
    private int getDrawTextWidth(Paint paint, String textContent) {
        float totalWidth = 0f;
        if (textContent != null && textContent.length() > 0) {
            int len = textContent.length();
            float[] widths = new float[len];
            paint.getTextWidths(textContent, widths);
            for (int j = 0; j < len; j++) {
                totalWidth += widths[j];
            }
        }
        return (int) Math.ceil(totalWidth);
    }

    /**
     * @param dpValue (DisplayMetrics類中屬性density)
     * @return
     */
    private int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public void setTextContent(String textContent) {
        this.textContent = textContent;
        invalidate();
    }

    public void setMSelected(boolean isSelected) {
        textPaint.setColor(isSelected ? Color.WHITE : selectedColor);
        paint.setStyle(isSelected ? Paint.Style.FILL_AND_STROKE : Paint.Style.STROKE);
        this.isSelected = isSelected;
        invalidate();
    }

    @Override
    public boolean isSelected() {
        return isSelected;
    }
}

要點分析

1.背景與文本內(nèi)容的繪制

計算好四個點的位置連線,TextView默認的文本內(nèi)容則設(shè)置為空字符串,采用drawText的方式來實現(xiàn)文本的顯示。需要注意的是計算文本的字號長度大小、顏色以及位于整個view的位置、偏移量等。

2.梯形范圍內(nèi)外的點擊事件處理

依照于設(shè)計,梯形內(nèi)的點擊才有響應,則要計算點擊的位置是否在梯形內(nèi),然后通過dispatchTouchEvent來做事件的分發(fā)。

 /**
     * 判斷點擊的位置是否在要求的范圍內(nèi)
     * @param event
     * @return
     */
    public boolean isInRegion(MotionEvent event) {
        RectF rectF = new RectF();
        linePath.computeBounds(rectF, true);
        mRegion.setPath(linePath, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));
        return mRegion.contains((int) event.getX(), (int) event.getY());
    }

3.其它自定義屬性

依據(jù)于需求來定,注意invalidate。

最后,完整代碼

https://github.com/ganshenml/LadderTextView

以上就是Android實現(xiàn)梯形TextView效果的詳細內(nèi)容,更多關(guān)于Android 梯形TextView的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 很棒的Android彈幕效果實例

    很棒的Android彈幕效果實例

    這篇文章主要為大家詳細介紹了很棒的Android彈幕效果實例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • ViewPager+Fragment實現(xiàn)側(cè)滑導航欄

    ViewPager+Fragment實現(xiàn)側(cè)滑導航欄

    這篇文章主要為大家詳細介紹了ViewPager+Fragment實現(xiàn)側(cè)滑導航欄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Android Studio 3.1.3升級至3.6.1后舊項目的兼容操作方法

    Android Studio 3.1.3升級至3.6.1后舊項目的兼容操作方法

    這篇文章主要介紹了Android Studio 3.1.3升級至3.6.1后舊項目的兼容操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Android開發(fā)中用Kotlin編寫LiveData組件教程

    Android開發(fā)中用Kotlin編寫LiveData組件教程

    LiveData是Jetpack組件的一部分,更多的時候是搭配ViewModel來使用,相對于Observable,LiveData的最大優(yōu)勢是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動生命周期狀態(tài)的時候才會更新數(shù)據(jù)
    2022-12-12
  • Android使用OKHTTP解析JSON數(shù)據(jù)的實例代碼

    Android使用OKHTTP解析JSON數(shù)據(jù)的實例代碼

    本篇文章主要介紹了Android使用OKHTTP解析JSON數(shù)據(jù)的實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android使用WebView實現(xiàn)離線閱讀功能

    Android使用WebView實現(xiàn)離線閱讀功能

    這篇文章主要介紹了Android使用WebView實現(xiàn)離線閱讀功能,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下
    2021-04-04
  • Android?Admob接入原理及完整教程示例

    Android?Admob接入原理及完整教程示例

    這篇文章主要為大家介紹了Android?Admob接入原理及完整教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Android draw9patch 圖片制作與使用詳解

    Android draw9patch 圖片制作與使用詳解

    本文主要介紹Android draw9patch的圖片使用和制作,這里詳細說明如何操作,并幫大家整理了幾句口令,幫助大家記住,有興趣的小伙伴可以參考下
    2016-09-09
  • Android 使用viewpager實現(xiàn)無限循環(huán)(定時+手動)

    Android 使用viewpager實現(xiàn)無限循環(huán)(定時+手動)

    這篇文章主要介紹了Android 使用viewpager實現(xiàn)無限循環(huán)(定時+手動)的相關(guān)資料,需要的朋友可以參考下
    2015-11-11
  • Android解析服務器端發(fā)來的xml數(shù)據(jù)示例

    Android解析服務器端發(fā)來的xml數(shù)據(jù)示例

    Android跟服務器交互數(shù)據(jù),有時數(shù)據(jù)量大時,就需要以xml形式的交互數(shù)據(jù),下面與大家分享下使用XmlPullParser來解析xml數(shù)據(jù),感興趣的朋友可以參考下哈
    2013-06-06

最新評論