最近项目中用到了一个可拖动的进度条,并且在当前进度的末端的icon上,添加当前进度。毫无疑问,当前进度只有在icon的中心才好看。左搜右搜,怎么都没有找到。后来,我就很生气,你都不会自己写一个吗?硬着头皮,想了想原理。发现是so easy!
先贴几张图片,让大家清楚我在啰嗦什么
简单叙述一下原理:既然文字要位于icon的中心,则首先要定位到Icon的位置。
在水平方向上:icon走的路程=进度条长度-icon的长度;然后计算出每一个进度icon需要移动的位置:((mScreenWidth - mDrawableWidth) / (double) mTotalSeconds); 由于文字是从左侧进行定位的,计算出文字块占用的空间,以便定位到文字在icon上的左侧位置:相关代码如下:
/**
* 获取显示字样占用的空间
*/
TextPaint paint = new TextPaint();
paint.setTextSize(mProgressView.getTextSize());
Rect rect = new Rect();
String tt = "00:00";
paint.getTextBounds(mStartTimeStr, 0, tt.length(), rect);
mTextWidth = rect.width();
mTextHeight = rect.height();
/**定位文字在icon左侧的相对坐标
*/
(mDrawableWidth - mTextWidth) / 2
在垂直方向上:icon没有移动,只需要在起始位置定位到icon中心即可;为了可以使用layout方法,在这里给代表当前进度的TextView添加了一个ViewGroup:
<gu.chuan.hang.PlaySeekbarGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-3dp" >
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:includeFontPadding="false"
android:singleLine="true"
android:text="00:00"
android:textColor="#f00"
android:textSize="12sp" />
</gu.chuan.hang.PlaySeekbarGroup>
package gu.chuan.hang;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
public class PlaySeekbarGroup extends ViewGroup {
public PlaySeekbarGroup(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public PlaySeekbarGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public PlaySeekbarGroup(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
PS:1.可以看到这个自定义ViewGroup什么都没有做。onLayout()方法是ViewGroup才会有的,在布局的时候,调用完TextView的layout(),还需要调用parent组件的onLayout(),最终才能确定,TextView的位置。在这里我大胆猜测是,代表当前进度的TextView不想让parent组件“管闲事”(影响自己的位置)。所以在外层包裹了一个空的ViewGroup;
2.android:layout_marginTop=”-3dp”这种用法很少见,但有的时候不得不用啊,TextView中文本与TextView顶端并不是对齐的,何况又加上一层包裹(ViewGroup),为了与seekbar实现垂直对齐,就向上偏移吧。
讲解了折磨多,看一下OnSeekChangeListener吧:
private class OnSeekBarChangeListenerImp implements
SeekBar.OnSeekBarChangeListener {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
int layoutLeft = (int) (progress * mMoveStep)
+ (mDrawableWidth - mTextWidth) / 2;
System.err.println("layoutLeft" + layoutLeft);
mProgressView.layout(layoutLeft, mTextlayoutTop, mScreenWidth, 80);
String showText = getTimeBySeconds(progress, mStartTimeStr);
mProgressView.setText(showText.substring(3));
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
本人菜鸟一枚,讲解的不怎么清楚。为了大家能更好的体会,现附上Demo:
http://download.csdn.net/detail/guchuanhang/9145923