环境:android studio 、java
项目需要在进度条的滑块上显示进度值并居中, UI设计图:
代码实现效果图:
浅色模式:
深色模式:
由于一开始没有自定义seekbar, 使用源码Seekar, 滑块要求时带圆角,所以需要设置thumbOffset 使滑条和滑块衔接顺畅。想实现UI效果,需要对文字与滑条的左边距,进行计算处理。
布局:
<RelativeLayout
android:layout_width="1335dp"
android:layout_height="46dp"
android:layout_marginLeft="24dp"
android:layout_marginRight="24dp"
app:layout_constraintStart_toEndOf="@+id/dark"
app:layout_constraintEnd_toStartOf="@+id/light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:thumbOffset="5dp"
android:splitTrack="false"
android:thumb="@drawable/brightness_adjustment_slider"
android:progressDrawable="@drawable/brightness_adjustment_bg"/>
<TextView
android:id="@+id/seekbar_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/harmonyos_sans_sc_regular"
android:textColor="@color/font_color"
android:singleLine="true"
android:textSize="24sp"/>
</RelativeLayout>
实现文字居中的java代码:
int textViewWidth = mSeekBarValueTextView.getWidth();
int textViewHeight = mSeekBarValueTextView.getHeight();
int thumbWidth = mSeekBar.getThumb().getIntrinsicWidth();
int thumbHeight = mSeekBar.getThumb().getIntrinsicHeight();
int thumbOff = mSeekBar.getThumbOffset(); // 滑块偏移距离
int available = mSeekBar.getWidth() - mSeekBar.getPaddingLeft() - mSeekBar.getPaddingRight(); // seekbar 有效宽
int tempValue = value - mMin;
// 进度百分比
float progressRatio = (float) tempValue / (mSeekBar.getMax() - mSeekBar.getMin());
// 文字相对滑块左边的距离
int textInThumbOff = (thumbWidth-textViewWidth)/2;
available = available - thumbWidth;
available += thumbOff*2;
final int thumbPos = (int) (progressRatio * available + 0.5f); // 滑块的左起始位置
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mSeekBarValueTextView.getLayoutParams();
int textTopPos = (thumbHeight- textViewHeight)/2; // 文字上方的位置
int textLeftPos = thumbPos+ textInThumbOff + mSeekBar.getPaddingLeft() - thumbOff; // 文字左边的位置,mSeekBar.getPaddingLeft() - thumbOff 为X轴上的偏移量
params.setMargins(textLeftPos, textTopPos,0, 0);
mSeekBarValueTextView.setLayoutParams(params);
java 中文字左边位置计算参考seekbar原生代码滑块位置实现:
frameworks/base/core/java/android/widget/AbsSeekBar.java:
/**
* Updates the thumb drawable bounds.
*
* @param w Width of the view, including padding
* @param thumb Drawable used for the thumb
* @param scale Current progress between 0 and 1
* @param offset Vertical offset for centering. If set to
* {@link Integer#MIN_VALUE}, the current offset will be used.
*/
private void setThumbPos(int w, Drawable thumb, float scale, int offset) {
int available = w - mPaddingLeft - mPaddingRight;
final int thumbWidth = thumb.getIntrinsicWidth();
final int thumbHeight = thumb.getIntrinsicHeight();
available -= thumbWidth;
// The extra space for the thumb to move on the track
available += mThumbOffset * 2;
final int thumbPos = (int) (scale * available + 0.5f);
final int top, bottom;
if (offset == Integer.MIN_VALUE) {
final Rect oldBounds = thumb.getBounds();
top = oldBounds.top;
bottom = oldBounds.bottom;
} else {
top = offset;
bottom = offset + thumbHeight;
}
final int left = (isLayoutRtl() && mMirrorForRtl) ? available - thumbPos : thumbPos;
final int right = left + thumbWidth;
final Drawable background = getBackground();
if (background != null) {
final int offsetX = mPaddingLeft - mThumbOffset;
final int offsetY = mPaddingTop;
background.setHotspotBounds(left + offsetX, top + offsetY,
right + offsetX, bottom + offsetY);
}
// Canvas will be translated, so 0,0 is where we start drawing
thumb.setBounds(left, top, right, bottom);
updateGestureExclusionRects();
}
本文为项目效果实现思路记录所用