先看效果图
1.先讲下思路,先用xml写单个刻度然后用适配器加载,并设置刻
1. xml
ruler_unit_horizontal.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00000000"> <FrameLayout android:id="@+id/ruler_frame" android:layout_width="@dimen/dimen_dp_20" android:layout_height="@dimen/dimen_dp_25" android:paddingBottom="@dimen/dimen_dp_4" android:orientation="vertical"> <TextView android:id="@+id/ruler_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:paddingBottom="@dimen/dimen_dp_4" android:text="250" android:textColor="@color/white" android:textSize="@dimen/dimen_sp_6" /> <LinearLayout android:id="@+id/ruler_linear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:orientation="horizontal"> <View android:id="@+id/ruler_img" android:layout_width="@dimen/dimen_dp_1" android:layout_height="@dimen/dimen_dp_7" android:layout_gravity="bottom|center_horizontal" android:background="@color/white" android:scaleType="fitXY" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right"> <View android:layout_width="@dimen/dimen_dp_1" android:layout_height="@dimen/dimen_dp_4" android:layout_gravity="bottom" android:background="@color/white" android:scaleType="fitXY" /> </LinearLayout> </FrameLayout> </RelativeLayout> 2.适配器RulerAdapterpublic class RulerAdapter extends RecyclerView.Adapter<RulerAdapter.RulerViewHolder> { private String TAG = "RulerAdapter"; public void setList(int list) { this.list = list; notifyDataSetChanged(); } private int list = 350; private Context context; private int width; public RulerAdapter(Context context) { this.context = context; } @Override public RulerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.ruler_unit_horizontal, null); return new RulerViewHolder(view); } @Override public void onBindViewHolder(RulerViewHolder holder, int position) { TextView tv = holder.numberView; View view = holder.rulerView; FrameLayout frameLayout = holder.frameLayout; if (frameLayout != null) { if (position == 0) { tv.setText(0 + ""); }else { float number=(float)position*5/10; tv.setText(number+""); } } } @Override public int getItemCount() { return list; } class RulerViewHolder extends RecyclerView.ViewHolder { TextView numberView; View rulerView; FrameLayout frameLayout; public RulerViewHolder(View arg0) { super(arg0); numberView = (TextView) arg0.findViewById(R.id.ruler_num); rulerView = (View) arg0.findViewById(R.id.ruler_img); frameLayout = (FrameLayout) arg0.findViewById(R.id.ruler_frame); } } }3.自定义 RecyclerViewpublic class RulerView extends RecyclerView { private static final String TAG = "RulerView"; RulerViewListener rulerViewListener = null; @Override public RulerAdapter getAdapter() { return adapter; } RulerAdapter adapter; public void setRulerViewListener(RulerViewListener rulerViewListener) { this.rulerViewListener = rulerViewListener; } public interface RulerViewListener { void onScrollChanged(int l, int t); /** * 是否拖拽 * @param isDraggingMove */ void stateChanged(boolean isDraggingMove); } public RulerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); if (!isInEditMode()) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RulerView); setLayoutParams(new LayoutParams(1000, LayoutParams.MATCH_PARENT)); ta.recycle(); init(context); } addScrollListener(); } LinearLayoutManager manager; private void init(Context context) { manager = new LinearLayoutManager(context); manager.setOrientation(LinearLayoutManager.HORIZONTAL); setLayoutManager(manager); adapter = new RulerAdapter(context); setAdapter(adapter); manager.scrollToPositionWithOffset(0, 0); } public void scrollToOffset(int x, int y) { if (x<0) { return; } Log.d(TAG, "child scrollToOffset dx: " +x +"-dy-->"+y); manager.scrollToPositionWithOffset(x,y); } @Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); if (state==SCROLL_STATE_DRAGGING) { rulerViewListener.stateChanged(true); }else { rulerViewListener.stateChanged(false); } } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); // l=getDistance(); // rulerViewListener.onScrollChanged(l,t); Log.d(TAG, "child onScrollChanged dx: " +l +"-dy-->"+t); } //记录滚动的总距离,类似view中的mScrollX和mScrollY private int sx = 0, sy = 0; //自己定义的滚动监听接口 public interface RecyclerScrollChangeListener{ void ScrollChange(int y); } private RecyclerScrollChangeListener mScrollListener = null; //重写scrollTo方法,通过内部的scrollBy实现scrollTo的功能 @Override public void scrollTo(int x, int y) { super.scrollTo(x, y); //计算滚动的相对距离,通过传进来的x和当前的sx差值就是scrollBy需要滚动的值 scrollBy(x - sx, y - sy); } private void addScrollListener(){ addOnScrollListener(new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { //因为dx和dy是相对上次的滚动距离,所以通过一开始的累加可以得到总的sx和sy sx += dx; sy += dy; super.onScrolled(recyclerView, dx, dy); rulerViewListener.onScrollChanged(sx,sy); //此处如果有需要监听滚动变化的话在这回调 Log.d(TAG, "child onScrollChanged dx: " +sx +"-dy-->"+sy); } }); } }
4. 使用
直接在对应的veiw中添加即可<skill.example.com.skillcreator.skill.view.rulerview.RulerView android:id="@+id/skill_rulerview" android:layout_width="match_parent" android:layout_height="@dimen/dimen_dp_22" android:background="#00000000" />
5.扩展与使用
根据个人项目的应用场景对其进行修改,如xml中一个刻度单元长度进行设置,并且增加小刻度个数,刻度位置等,
并且在代码中动态设置刻度尺的长度,监听当前滑动位置等