零.前言
在一些音乐或者音效应用中经常可以看到均衡器调节,之前在工作也做过类似效果,特此记录一下。效果如下图:
一.思路
- 自定义竖向SeekBar
- 自定义13段竖向SeekBar的Recycleview
- Recycleview 添加SeekBar上下滑动的悬浮文本提示或者顶部指示器
二.关键代码
1. 自定义一个矩形进度条(EqSquareProgress.java)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = (max - min) / step + 1;
for (int i = 0; i < count; i++) {
// 从下往上绘制
float startX = getPaddingLeft();
float lineHeight = ResUtils.getDimension(R.dimen.eq_progress_line);
float startY = getHeight() - ResUtils.getDimension(R.dimen.eq_progress_line_all) * i - lineHeight;
float stopX = getWidth() - getPaddingRight();
float stopY = startY;
if (min + i * step <= progress) {
paint.setColor(colorAdjusted);
} else {
paint.setColor(colorDefault);
}
if (adjusting) {
if (min + i * step <= progress) {
paint.setColor(colorAdjusting);
}
}
canvas.drawLine(startX, startY, stopX, stopY, paint);
// 绘制游标
if (adjusting && min + i * step == progress) {
paint.setColor(colorAdjusting);
float cursorMargin = ResUtils.getDimension(R.dimen.eq_progress_cursor_margin);
float cursorHeight = ResUtils.getDimension(R.dimen.eq_progress_cursor_size);
float cursorWidth = (float) (cursorHeight * 1.0F / 2 * Math.tan(Math.PI / 3));
cursorPath.reset();
cursorPath.moveTo(startX - cursorMargin, startY);
cursorPath.lineTo(startX - cursorMargin - cursorWidth, startY - cursorHeight * 1.0F / 2);
cursorPath.lineTo(startX - cursorMargin - cursorWidth, startY + cursorHeight * 1.0F / 2);
cursorPath.lineTo(startX - cursorMargin, startY);
cursorPath.close();
canvas.drawPath(cursorPath, paint);
cursorPath.reset();
cursorPath.moveTo(stopX + cursorMargin, stopY);
cursorPath.lineTo(stopX + cursorMargin + cursorWidth, stopY - cursorHeight * 1.0F / 2);
cursorPath.lineTo(stopX + cursorMargin + cursorWidth, stopY + cursorHeight * 1.0F / 2);
cursorPath.lineTo(stopX + cursorMargin, stopY);
this.cursorPath.close();
canvas.drawPath(cursorPath, paint);
}
}
}
2.自定义13段竖向SeekBar的Recycleview(EqSquareBars.java)
// adapter
private class ProgressAdapter extends RecyclerViewAdapter<DataBean> {
ProgressAdapter(Context context, List<DataBean> datas) {
super(context, datas);
}
@Override
public int getItemLayoutId(int viewType) {
return R.layout.view_eq_square_bars;
}
@Override
public void onBindViewHolder(com.flyaudio.lib.adapter.Adapter.ViewHolder<DataBean> holder) {
DataBean data = getData(holder.getItemPosition());
EqSquareProgress progressBar = holder.getView(R.id.pb_progress);
TextView tvTitle = holder.getView(R.id.tv_title);
progressBar.setProgress(data.value);
progressBar.setAdjusting(region == holder.getItemPosition());
tvTitle.setText(data.title);
setOnItemClickListener(EqSquareBars.this);
}
}
// 构造函数中初始化数据,添加Adapter
private void initData(Context context) {
this.dataBeans = new ArrayList<>();
this.adapter = new ProgressAdapter(context, dataBeans);
paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setTextSize(ResUtils.getDimension(R.dimen.eq_progress_font));
paintLine = new Paint();
paintLine.setColor(ResUtils.getColor(R.color.eq_progress_adjusting_color));
paintLine.setStrokeWidth(ResUtils.getDimension(R.dimen.eq_progress_top_line));
int[] eqFrequencies = EffectCommUtils.getFrequencies();
String[] titles = getResources().getStringArray(R.array.eq_titles_13);
for (int i = 0; i < titles.length; i++) {
DataBean dataBean = new DataBean();
dataBean.title = titles[i];
dataBean.freq = eqFrequencies[i];
this.dataBeans.add(dataBean);
}
}
private void initView() {
setAdapter(adapter);
setHasFixedSize(true);
setLayoutManager(new NoScrollLinearLayoutManager(getContext(), HORIZONTAL, false));
}
// 画顶部指示器
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
float y = getPaddingTop() + ResUtils.getDimension(R.dimen.eq_progress_font_height);
float item = ResUtils.getDimension(R.dimen.eq_progress_item_width);
float x;
float startX1, startY1, stopX1, stopY1;
float startX2, startY2, stopX2, stopY2;
startY1 = stopY1 = startY2 = stopY2 = y - 0.30F * ResUtils.getDimension(R.dimen.eq_progress_font_height);
if (region < REGION_BASS) {
// 低音
startX1 = getPaddingLeft() + item * 0.3F;
stopX1 = item * 1.5F;
startX2 = item * 2.4F;
stopX2 = item * 3.7F;
} else if (region < REGION_ALTO) {
// 中音
startX1 = item * 4.3F;
stopX1 = item * 6F;
startX2 = item * 7F;
stopX2 = item * 8.7F;
} else {
// 高音
startX1 = item * 9.2F;
stopX1 = item * 10.5F;
startX2 = item * 11.4F;
stopX2 = item * 12.7F;
}
for (int i = 0; i < REGION_COUNT; i++) {
x = item * (1.7F + 4.5F * i);
String text = i == 0 ? ResUtils.getString(R.string.bass) : i == 1 ? ResUtils.getString(R.string.alto) : ResUtils.getString(R.string.high);
if (i == 0 && region < REGION_BASS) {
paintText.setColor(ResUtils.getColor(R.color.eq_progress_adjusting_color));
} else if (i == 1 && region >= REGION_BASS && region < REGION_ALTO) {
paintText.setColor(ResUtils.getColor(R.color.eq_progress_adjusting_color));
} else if (i == 2 && region >= REGION_ALTO) {
paintText.setColor(ResUtils.getColor(R.color.eq_progress_adjusting_color));
} else {
paintText.setColor(ResUtils.getColor(R.color.text_color_normal8));
}
c.drawText(text, x, y, paintText);
}
c.drawLine(startX1, startY1, stopX1, stopY1, paintLine);
c.drawLine(startX2, startY2, stopX2, stopY2, paintLine);
}
三.github地址
https://github.com/dongpingwang/DaXiaViewDemo/tree/master/views/EqualizerView