本菜也是Android新手一枚,所以水平仅限于初级开发人员(大神勿喷),关于我写的博客有什么问题和错误,欢迎及时指出。
今天我们要实现用自定义view随着歌曲播放进度填充歌词的功能。
效果图:
首先说明设计思路:画文字 画两次,一次画全,一次不画全。第一次画直接画,第二次在图层中画,两次画的位置一样。
public class GeCiView extends TextView {
private int progress = 35;
private int backGroundTextColor = Color.GRAY;
private int progressTextColor = Color.BLUE;
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}
public int getBackGroundTextColor() {
return backGroundTextColor;
}
public void setBackGroundTextColor(int backGroundTextColor) {
this.backGroundTextColor = backGroundTextColor;
invalidate();
}
public int getProgressTextColor() {
return progressTextColor;
}
public void setProgressTextColor(int progressTextColor) {
this.progressTextColor = progressTextColor;
invalidate();
}
public GeCiView(Context context) {
this(context, null);
}
public GeCiView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GeCiView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
panit = new Paint();
clazz = TextView.class;
}
private Class<TextView> clazz = null;
private Paint panit;
@Override
protected void onDraw(Canvas canvas) {
//画文字,在textView类中,就是super,onDraw()
//画两次 就是调用两次super.onDraw
//第一次
try {
//获取mCurTextColor成员,他是表示绘制颜色的成员
Field field = clazz.getDeclaredField("mCurTextColor");
//修改mCurTextColor成员的访问权限
field.setAccessible(true);
//成员可以访问了,修改他的值
field.set(this, backGroundTextColor);
} catch (Exception e) {
e.printStackTrace();
}
super.onDraw(canvas);
//第二次绘制之前,先要开启一个图层
canvas.saveLayerAlpha(0, 0, getWidth() * progress/100, getHeight(), 255, canvas.ALL_SAVE_FLAG);
try {
//获取mCurTextColor成员,他是表示绘制颜色的成员
Field field = clazz.getDeclaredField("mCurTextColor");
//修改mCurTextColor成员的访问权限
field.setAccessible(true);
//成员可以访问了,修改他的值
field.set(this, progressTextColor);
} catch (Exception e) {
e.printStackTrace();
}
super.onDraw(canvas);
}
}
在这里值得注意的是TextView中的设置字体颜色的属性权限为private 所以利用反射来修改其访问权限。
在MainActivity中利用handler把每行字体的读完时间设置为两秒。(真正开发中依情况而定)
public class MainActivity extends AppCompatActivity {
private GeCiView mGeCiView = null;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1){
mGeCiView.setProgress(msg.arg1);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mGeCiView = (GeCiView) findViewById(R.id.geciView);
}
public void onclik(View view) {
mGeCiView.setProgress(0);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = Message.obtain();
message.what=1;
message.arg1=i;
mHandler.sendMessage(message);
}
}
}).start();
}
}
布局:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.panfengyu.day28textdemo.MainActivity">
<com.panfengyu.day28textdemo.GeCiView
android:id="@+id/geciView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="你还要我怎么样,要怎样"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onclik"
android:text="开始"
/>
</LinearLayout>