您的位置:首页 > 其它

带数字显示的自定义SeekBar

2016-10-14 11:12 344 查看
由于项目需要做个单向滑动SeekBar,而系统自带的SeekBar并没能提供滑块上面的数字,所以只能自定义了。

效果图如下:



使用方法如下:

<com.whoisaa.mseekbar.MSeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/bg_seekbar_progress_drawable"
android:thumb="@mipmap/icon_seekbar_thumb"
app:textBackground="@mipmap/bg_seekbar_display2"
app:textColor="@color/white"
app:textOrientation="top"
app:textSize="14sp"/>


SeekBar底部背景和进度背景

android:progressDrawable="@drawable/bg_seekbar_progress_drawable"


bg_seekbar_progress_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!-- 底部背景 -->
<item android:id="@android:id/background" android:height="15dp">
<shape>
<corners android:radius="10dp"/>
<size android:height="15dp" />
<solid android:color="#CBCBCB"/>
</shape>
</item>

<!-- 进度背景 -->
<item android:id="@android:id/progress" android:height="15dp">
<clip>
<shape>
<corners android:radius="10dp"/>
<size android:height="15dp" />
<solid android:color="#0069B6"/>
</shape>
</clip>
</item>

</layer-list>


滑块图片

android:thumb="@mipmap/icon_seekbar_thumb"


文字在滑块的顶部(top)或底部(bottom)

app:textOrientation="top"


滑块顶部(底部)文字背景图片

app:textBackground="@mipmap/bg_seekbar_display2"


attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MSeekBar">
<attr name="textSize" format="dimension" />
<attr name="textColor" format="color" />
<attr name="textBackground" format="reference" />
<attr name="textOrientation" format="enum">
<enum name="top" value="1" />
<enum name="bottom" value="2" />
</attr>
</declare-styleable>
</resources>


MSeekBar源码

package com.whoisaa.mseekbar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;

public class MSeekBar extends SeekBar {

/**
* SeekBar数值文字颜色
*/
private int mTextColor;

/**
* SeekBar数值文字大小
*/
private float mTextSize;

/**
* SeekBar数值文字内容
*/
private String mText;

/**
* SeekBar数值文字背景
*/
private Bitmap mBackgroundBitmap;

/**
* SeekBar数值文字背景宽高
*/
private float mBgWidth, mBgHeight;

/**
* 画笔
*/
private Paint mPaint;

/**
* SeekBar数值文字方向
*/
private int mTextOrientation;

/**
* SeekBar数值文字宽度
*/
private float mTextWidth;

/**
* SeekBar数值文字基线Y坐标
*/
private float mTextBaseLineY;

//文字方向
private static final int ORIENTATION_TOP = 1;
private static final int ORIENTATION_BOTTOM = 2;

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

public MSeekBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public MSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MSeekBar, defStyleAttr, 0);
int count = ta.getIndexCount();
for(int i = 0; i < count; i++) {
int index = ta.getIndex(i);
switch (index) {
case R.styleable.MSeekBar_textColor:
mTextColor = ta.getColor(index, Color.WHITE);
break;

case R.styleable.MSeekBar_textSize:
mTextSize = ta.getDimension(index, 15f);
break;

case R.styleable.MSeekBar_textBackground:
//获取文字背景图片的宽高
int bgResId = ta.getResourceId(index, R.mipmap.bg_seekbar_display1);
mBackgroundBitmap = BitmapFactory.decodeResource(getResources(), bgResId);
mBgWidth = mBackgroundBitmap.getWidth();
mBgHeight = mBackgroundBitmap.getHeight();
break;

case R.styleable.MSeekBar_textOrientation:
mTextOrientation = ta.getInt(index, ORIENTATION_TOP);
break;
}
}
ta.recycle();

//设置画笔
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize);

//设置文字显示方向
if(mTextOrientation == ORIENTATION_TOP) {
//设置SeekBar顶部数值文字预留空间,左右为数值背景图片的一半,顶部为数值背景图片高度加五的间隔
setPadding((int) Math.ceil(mBgWidth) / 2, (int) Math.ceil(mBgHeight) + 5, (int) Math.ceil(mBgWidth) / 2, 0);
} else {
//设置SeekBar顶部数值文字预留空间,左右为数值背景图片的一半,底部为数值背景图片高度加五的间隔
setPadding((int) Math.ceil(mBgWidth) / 2, 0, (int) Math.ceil(mBgWidth) / 2, (int) Math.ceil(mBgHeight) + 5);
}
}

@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);

getTextLocation();
Rect bgRect = getProgressDrawable().getBounds();
//计算数值背景X坐标
float bgX = bgRect.width() * getProgress() / getMax();
//计算数值背景Y坐标
float bgY = 0;
if(mTextOrientation == ORIENTATION_BOTTOM) {
bgY = mBgHeight + 10;
}

//计算数值文字X坐标
float textX = bgX + (mBgWidth - mTextWidth) / 2;
float textY = (float) (mTextBaseLineY + bgY + (0.16 * mBgHeight / 2) - 10);

//绘制文字和背景
canvas.drawBitmap(mBackgroundBitmap, bgX, bgY, mPaint);
canvas.drawText(mText, textX, textY, mPaint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
invalidate();
return super.onTouchEvent(event);
}

/**
* 计算SeekBar数值文字的显示位置
*/
private void getTextLocation() {
Paint.FontMetrics fm = mPaint.getFontMetrics();
mText = "¥" + getProgress();
//测量文字宽度
mTextWidth = mPaint.measureText(mText);
//计算文字基线Y坐标
mTextBaseLineY = mBgHeight / 2 - fm.descent + (fm.descent - fm.ascent) / 2;
}
}


在MainActivity中调用和普通SeekBar一样

package com.whoisaa.mseekbar;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {

private TextView mTextView1, mTextView2;
private MSeekBar mSeekBar1, mSeekBar2;

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

mTextView1 = (TextView) findViewById(R.id.tv_main1);
mTextView2 = (TextView) findViewById(R.id.tv_main2);
mSeekBar1 = (MSeekBar) findViewById(R.id.sb_main1);
mSeekBar2 = (MSeekBar) findViewById(R.id.sb_main2);
mSeekBar1.setOnSeekBarChangeListener(this);
mSeekBar2.setOnSeekBarChangeListener(this);
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(seekBar.equals(mSeekBar1)) {
mTextView1.setText("滑块一当前值为" + progress);
} else if(seekBar.equals(mSeekBar2)) {
mTextView2.setText("滑块二当前值为" + progress);
}
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}
}


去Github查看源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: