使用 RecyclerView 实现刻度尺(或标尺)的功能,自定义Item 和适配器来完成。具体实现步骤:
1. 定义RecyclerView Item 即 刻度尺的布局文件layout_item_scale.xml:
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="bottom|center_horizontal">
<TextView
android:id="@+id/scale_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10sp"
android:gravity="center"
android:textColor="#000000"
android:layout_marginBottom="10dp"
tools:ignore="SmallSp" />
<View
android:id="@+id/scale_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
2. 创建 RecyclerView 的适配器:
public class ScaleAdapter extends RecyclerView.Adapter<ScaleAdapter.ScaleViewHolder> {
private final int itemCount;
public ScaleAdapter(int itemCount) {
this.itemCount = itemCount;
}
@NonNull
@Override
public ScaleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item_scale, parent, false);
return new ScaleViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ScaleViewHolder holder, int position) {
holder.bind(position);
}
@Override
public int getItemCount() {
return itemCount;
}
public static class ScaleViewHolder extends RecyclerView.ViewHolder {
private final View scaleLine;
private final TextView scaleValue;
private final float density;
public ScaleViewHolder(@NonNull View itemView) {
super(itemView);
scaleLine = itemView.findViewById(R.id.scale_line);
scaleValue = itemView.findViewById(R.id.scale_value);
density = itemView.getResources().getDisplayMetrics().density;
}
public void bind(int position) {
int longestTickHeight = (int) (33 * density); // 最长刻度高度
int mediumTickHeight = (int) (23 * density); // 中长刻度高度
int shortTickHeight = (int) (10 * density); // 短刻度高度
int space = (int) (10 * density);
int oneSpace = (int) (1 * density);
if (position % 10 == 0) {
// 每10个刻度为一个长刻度,显示刻度值
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(2, longestTickHeight);
scaleLine.setLayoutParams(params);
scaleLine.setBackgroundColor(0xFFCDCDCD);
scaleValue.setText(String.valueOf(position / 10 + 76));
} else if (position % 5 == 0) {
// 每5个刻度为一个中等刻度
scaleLine.setLayoutParams(new LinearLayout.LayoutParams(2, mediumTickHeight));
scaleLine.setBackgroundColor(0xFFCDCDCD);
scaleValue.setText("");
} else {
// 其他为短刻度
scaleLine.setLayoutParams(new LinearLayout.LayoutParams(2, shortTickHeight));
scaleLine.setBackgroundColor(0xFFCDCDCD);
scaleValue.setText("");
}
LinearLayout.LayoutParams params;
if (position % 2 == 0) {
params = new LinearLayout.LayoutParams(space * 2, LinearLayout.LayoutParams.WRAP_CONTENT);
} else {
params = new LinearLayout.LayoutParams(oneSpace, LinearLayout.LayoutParams.WRAP_CONTENT);
}
params.bottomMargin = space;
scaleValue.setLayoutParams(params);
}
}
}
3. 刻度尺 item 分为两种宽度:
if (position % 2 == 0) { // 偶数设置 2个宽度 space * 2
params = new LinearLayout.LayoutParams(space * 2, LinearLayout.LayoutParams.WRAP_CONTENT);
} else { // 奇数设置 1个宽度,即刻度尺的粗细
params = new LinearLayout.LayoutParams(oneSpace, LinearLayout.LayoutParams.WRAP_CONTENT);
}
4. 在 Activity 或 Fragment 中设置 RecyclerView:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
// 设置初始的左右内边距
val leftRightPadding = recyclerView.width / 2
recyclerView.setPadding(leftRightPadding, 0, leftRightPadding, 0)
recyclerView.setClipToPadding(false)
// 这里假设最大值为100
val scaleAdapter = ScaleAdapter(100)
recyclerView.adapter = scaleAdapter
}
}
5. 滚动刻度尺到指定为止:
val position = (channel?:60) - 50
recyclerView.post {
recyclerView.scrollToPosition(position)
}
6. 滚动监听,获取停止后的数据:
// 添加 LinearSnapHelper
val snapHelper = LinearSnapHelper()
snapHelper?.attachToRecyclerView(recyclerView)
// 滚动监听
recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
// 停止动作
if (RecyclerView.SCROLL_STATE_IDLE == newState) {
// 防止快速滚动处理
if (System.currentTimeMillis() - tempTime < 200) {
return
}
val centerView = snapHelper?.findSnapView(recyclerView.layoutManager)
if (centerView != null) {
// 获取对应的刻度值
val index = recyclerView.layoutManager?.getPosition(centerView)
}
tempTime = System.currentTimeMillis()
}
}
})