SeekBar is no stranger to development. The default SeekBar does not display the progress. Of course, it is also possible to use toast or copywriting to display it in real time. Can it be displayed only when moving? It is not displayed by default. Of course, there are fancy three parties on the Internet. There are too many classes, but I just want to add a bubble that can be displayed along with the movement on the basis of SeekBar~
Let's take a look at the effect first:
This article may meet your needs
1. Native SeekBar is used without rewriting
2. The amount of changes is small and will not have any impact on the control
3. Flexible use, Utils use, copy and paste can be used
4. Flexible style, your own writing style
Let me talk about the principle first:
1. First of all, the most basic thing is how to display it without affecting the original controls?
Answer: PopupWindow, it only needs to get the corresponding target control to specify the display position
2. How to follow the movement?
Answer: PopupWindow itself will not move dynamically, you only need to set a control in the pop-up window to let the control move can
Specific implementation
Get the control, use PopupWindow to display it near the control, and dynamically set the position of the sub-control in the pop-up window according to the progress of the SeekBar
use
Here is the SeekBar mobile monitoring, the three methods here plus the corresponding methods
mDataBind.controlVolumeSeekbar.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
//滑块移动
SeekBarPopUtils.move(progress,seekBar!!)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
//滑块按下
SeekBarPopUtils.showPop(seekBar!!)
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
//滑块松开
SeekBarPopUtils.dismiss()
}
})
SeekBarPopUtils (Kotlin)
The tvPopTxt here is the small bubble in the picture above. If you need other styles, you can directly write them in the pop-up window layout
/**
* SeekBar移动时弹出对应的气泡加数字*/
@SuppressLint("StaticFieldLeak")
object SeekBarPopUtils {
private var popWin: PopupWindow? = null
private var clPopPar: ConstraintLayout? = null
private var tvPopTxt: TextView? = null
fun showPop(seekBar: SeekBar){
popWin = PopupWindow()
val mPopView = LayoutInflater.from(BaseApplication.getContext()).inflate(R.layout.item_popup_win,null,false)
clPopPar = mPopView.findViewById<ConstraintLayout>(R.id.cl_pop_par)
tvPopTxt = mPopView.findViewById<TextView>(R.id.tv_pop_txt)
popWin?.contentView = mPopView
popWin?.height = AppHelper.dp2px(30)
popWin?.width = seekBar.width
popWin?.showAsDropDown(seekBar,0,-(AppHelper.dp2px(30) + popWin!!.height))
}
fun move(progress: Int,seekBar: SeekBar){
if (clPopPar != null){
val tvPopWidth = AppHelper.dp2px(40)
val params: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
tvPopWidth, AppHelper.dp2px(30)
)
params.startToStart = clPopPar!!.id
params.marginStart = (seekBar.width - tvPopWidth)/100 * progress + tvPopWidth/3
tvPopTxt?.layoutParams = params
tvPopTxt?.text = progress.toString()
}
}
fun dismiss(){
popWin?.dismiss()
popWin = null
clPopPar = null
tvPopTxt = null
}
}
SeekBarPopUtils (Java)
public class SeekBarPopUtils {
private static PopupWindow popWin = null;
private static ConstraintLayout clPopPar = null;
private static TextView tvPopTxt = null;
public static void showPop(SeekBar seekBar){
popWin = new PopupWindow();
View mPopView = LayoutInflater.from(App.getInstance().getBaseContext()).inflate(R.layout.item_popup_win,null,false);
clPopPar = mPopView.findViewById(R.id.cl_pop_par);
tvPopTxt = mPopView.findViewById(R.id.tv_pop_txt);
popWin.setContentView(mPopView);
popWin.setHeight(dp2px(30));
popWin.setWidth(seekBar.getWidth());
popWin.showAsDropDown(seekBar,0,-(dp2px(30) + popWin.getHeight()));
}
public static void move(int progress,SeekBar seekBar){
if (clPopPar != null){
int tvPopWidth = dp2px(40);
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(
tvPopWidth, dp2px(30)
);
params.startToStart = clPopPar.getId();
params.setMarginStart((seekBar.getWidth() - tvPopWidth)/100 * progress + tvPopWidth/3);
tvPopTxt.setLayoutParams(params);
tvPopTxt.setText(progress + "");
}
}
private static int dp2px(int dpVal){
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
(float) dpVal,
App.getInstance().getBaseContext().getResources().getDisplayMetrics()
);
}
public static void dismiss(){
popWin.dismiss();
popWin = null;
clPopPar = null;
tvPopTxt = null;
}
}
item_popup_win code
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_pop_par"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="30dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/tv_pop_txt"
android:layout_width="40dp"
android:layout_height="match_parent"
android:gravity="center"
app:layout_constraintStart_toStartOf="parent"
android:background="@drawable/bg_ffffff_12"
android:textSize="16sp"
android:textColor="#000000"
tools:text = "999"/>
</androidx.constraintlayout.widget.ConstraintLayout>
bg_ffffff_12
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="ResourceName">
<solid android:color="#FFFFFF" />
<corners android:radius="12dp" />
</shape>
AppHelper.dp2px
fun dp2px(dpVal: Int): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dpVal.toFloat(),
BaseApplication.getContext().resources.displayMetrics
).toInt()
}