一、需求描述
最近,公司要做国际化,而且有个界面的右上角要做成类似如下所示的样式,
最开始的这个右上角角标是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
自定义的属性
斜边展示的模式