如何自定义一个45度旋转的TextView,实现类似右上角文字角标的效果

一、需求描述
最近,公司要做国际化,而且有个界面的右上角要做成类似如下所示的样式,

最开始的这个右上角角标是UI直接出图给我的,然后发现UI给了我好几个国家的角标,每个国家两张图片,分别是 xdpi分辨率下和xxdpi分辨率的。这样的话,关这个角标就得十几张小图片,oh my god,虽然每张图片也不大,才2k左右,但是加起来也有几十k啊,如果以后要支持的国家越来越多咋办? 因此我决定还是优化一下,减少apk的体积。

二、看实现效果


三、实现过程
3.1 自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RotateTextView">
        <!--文本旋转的角度-->
        <attr name="degree" format="integer" />
    </declare-styleable>
</resources>

自定义一个属性【degree】,表示文本旋转的角度3.2 自定义旋转的TextView

package com.oyp.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.Gravity;

/**
 * 实现一个可选择的TextView,作用是:右上角的角标45°文本提示
 * </p>
 * created by OuyangPeng at 2019/1/10 下午 08:19
 *
 * @author OuyangPeng
 */
public class RotateTextView extends android.support.v7.widget.AppCompatTextView {
    /**
     * 默认选择45°角
     */
    private static final int DEFAULT_DEGREES = 45;

    /**
     * 文本旋转的角度
     */
    private int mDegrees;

    public RotateTextView(Context context) {
        this(context, null);
    }

    public RotateTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setGravity(Gravity.CENTER);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RotateTextView);
        mDegrees = a.getInteger(R.styleable.RotateTextView_degree, DEFAULT_DEGREES);
        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();
        canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
        canvas.rotate(mDegrees, this.getWidth() / 2f, this.getHeight() / 2f);
        super.onDraw(canvas);
        canvas.restore();
    }

    /**
     * 改变文本选择的角度
     *
     * @param degrees 文本旋转的角度
     */
    public void setDegrees(int degrees) {
        mDegrees = degrees;
        invalidate();
    }

}

这个自定义的RotateTextView,继承自TextView,将TextView的文本内容旋转指定的degree角度。

3.3 引用自定义的RotateTextView
在下面的布局文件中,引用自定义的RotateTextView,并设置好一张默认的背景图,背景图资源如下所示:backgroud.png

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.oyp.view.RotateTextView
        android:id="@+id/rotate_textview"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentRight="true"
        android:background="@drawable/backgroud"
        android:gravity="center"
        android:paddingBottom="45dp"
        android:text="欧阳鹏"
        android:textColor="#fff"
        android:textSize="20sp"
        app:degree="45" />

    <TextView
        android:id="@+id/rotate_degrees"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/rotate_textview"
        android:gravity="center"
        android:padding="10dp" />

    <SeekBar
        android:id="@+id/sb_rotate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/rotate_degrees"
        android:layout_marginTop="20dp"
        android:max="100"
        android:progress="30" />

    <Button
        android:id="@+id/bt_change_bg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/sb_rotate"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:text="替换TextView背景" />

</RelativeLayout>


3.4 在Activity中控制旋转角度,以及替换背景

package com.oyp.view;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;


public class MainActivity extends Activity {
    RotateTextView mText;
    TextView degrees;
    boolean isFirst = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mText = (RotateTextView) findViewById(R.id.rotate_textview);
        degrees = (TextView) findViewById(R.id.rotate_degrees);
        SeekBar sbLean = (SeekBar) findViewById(R.id.sb_rotate);
        sbLean.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mText.setDegrees(progress);
                degrees.setText("倾斜度:" + progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        findViewById(R.id.bt_change_bg).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mText.setBackgroundResource(isFirst ? R.drawable.backgroud2 : R.drawable.backgroud);
                isFirst = !isFirst;
            }
        });

    }

}


四、源代码
https://github.com/ouyangpeng/RotaTextView
五、提升
写完后,后来发现github上有个很好的例子,如下所示:
实现方式更好,完全由paint画出来的,这样又可以节省背景图片资源,并且以后如果UI替换背景颜色之类的,只需要修改相应的颜色值即可,完全不用加新的背景颜色。 我已经在项目中替换成下面的这种完全自定义TextView的方式了。

大家可以参考下!

https://github.com/HeZaiJin/SlantedTextView
我fork后,加入了注释便于理解,修改了一些代码,可参考下

https://github.com/ouyangpeng/SlantedTextView


自定义的属性

斜边展示的模式

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值