Android - 사용자 지정 컨트롤 수직 TextView

14438 단어
정상적인 상황에서 TextView의 텍스트 내용은 수평으로 표시되는데 어떻게 내용을 수직으로 표시할 수 있습니까? 그래서 사용자 정의 컨트롤러가 TextView를 계승하고 onDraw 함수를 다시 쓰기를 시도했습니다. 코드는 다음과 같습니다.
    @Override  
    protected void onDraw(Canvas canvas) {  
        canvas.rotate(-90);  
        canvas.translate(-getHeight(), 0);  
        super.onDraw(canvas);  
    }

이상의 실현은 내용을 수직으로 표시할 수 있지만 너비와 높이가 어울리지 않는 문제가 존재한다. 예를 들어 지정한 너비에서 수직으로 보이는 문자가 줄을 바꿀 수 있는데 이것은 내가 원하는 결과가 아니다.나중에 인터넷에서 한 친구의 글을 찾았는데 마침 이 문제를 해결하여 대신께 경의를 표합니다.몇 가지 정리와 수정을 한 후에 최종 코드는 다음과 같다.
package com.example.sportdemo;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint.Align;
import android.graphics.Path;
import android.graphics.Rect;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;

public class VerticalTextView extends View {
    private final static int DEFAULT_TEXT_SIZE = 18;
    private final static int DEFAULT_TEXT_COLOR = 0x00000000;
    private final static int DIRECTION_TTB = 0;
    private final static int DIRECTION_BTT = 1;

    private String mText = "H";
    private TextPaint mTextPaint = new TextPaint();
    private Rect mTextRect = new Rect();
    private Path path = new Path();
    private int mDirection;

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

    public VerticalTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VerticalTextView);
        CharSequence text = a.getString(R.styleable.VerticalTextView_text);
        if (text != null) {
            mText = text.toString();
        }
        int textSize = a.getDimensionPixelOffset(R.styleable.VerticalTextView_textSize, DEFAULT_TEXT_SIZE);
        if (textSize > 0) {
            mTextPaint.setTextSize(textSize);
        }
        
        int textColor = a.getColor(R.styleable.VerticalTextView_textColor, DEFAULT_TEXT_COLOR);
        mTextPaint.setColor(textColor);
        mDirection = a.getInt(R.styleable.VerticalTextView_direction, DIRECTION_BTT);
        a.recycle();
    }

    @SuppressLint("NewApi")
    private final void init() {
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(DEFAULT_TEXT_SIZE);
        mTextPaint.setColor(DEFAULT_TEXT_COLOR);
        mTextPaint.setTextAlign(Align.CENTER);
    }

    public void setText(String text) {
        mText = text;
        requestLayout();
        invalidate();
    }
    
    public void setText(int resId) {
        mText = getContext().getResources().getText(resId).toString();
        requestLayout();
        invalidate();
    }

    public void setTextSize(int size) {
        mTextPaint.setTextSize(size);
        requestLayout();
        invalidate();
    }

    public void setTextColor(int color) {
        mTextPaint.setColor(color);
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mTextPaint.getTextBounds(mText, 0, mText.length(), mTextRect);
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    private int measureWidth(int measureSpec) {
        int width = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            width = specSize;
        } else {
//            width = mTextRect.height() + getPaddingLeft() + getPaddingRight();
            width = mTextRect.height();
            if (specMode == MeasureSpec.AT_MOST) {
                width = Math.min(width, specSize);
            }
        }
        return width;
    }

    private int measureHeight(int measureSpec) {
        int height = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            height = specSize;
        } else {
//            height = mTextRect.width() + getPaddingTop() + getPaddingBottom();
            height = mTextRect.width();
            if (specMode == MeasureSpec.AT_MOST) {
                height = Math.min(height, specSize);
            }
        }
        return height;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int startX = 0;
        int startY = 0;
        int stopY = getHeight();

        if (mDirection == DIRECTION_TTB) {
            startX = (getWidth() >> 1) - (mTextRect.height() >> 1);
            path.moveTo(startX, startY);
            path.lineTo(startX, stopY);
        }
        else {
            startX = (getWidth() >> 1) + (mTextRect.height() >> 1);
            path.moveTo(startX, stopY);
            path.lineTo(startX, startY);
        }
        canvas.drawTextOnPath(mText, path, 0, 0, mTextPaint);
    }
}

Xml 레이아웃 파일:
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
                
        <com.example.sportdemo.VerticalTextView 
            xmlns:demo="http://schemas.android.com/apk/res/com.example.sportdemo" 
            android:id="@+id/vtv"
            android:layout_width="40dp"
            android:layout_height="120dp"
            android:background="@color/black"            
            demo:text="helloworld"
            demo:textColor="@color/white"
            demo:textSize="20sp"
            demo:direction="bottomtotop" />
        
    LinearLayout>

여기서 강조해야 할 것은drawTextOnPath가 4.1 이전 시스템에서 하드웨어 가속을 켜는 상황에서 우리가 원하는 효과를 얻지 못했기 때문에 그 결과 그려진 텍스트가 표시되지 않기 때문에 아래 코드를 통해 하드웨어 가속을 사용하지 않는다는 것이다.
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }

 
순전히 학습 노트이니 시정을 환영합니다. 
전재 대상:https://www.cnblogs.com/biyaxiong/p/3784246.html

좋은 웹페이지 즐겨찾기