ListView个性化滑动指示器酷炫效果

前几天看到有好多人搞了一个listView的一个指示特效。然后自己参考了一下

面对这样的效果年会想起来几种思路?
- 自定义scrollView+scrollBar
- 自定义ListView+自定义ScrollBar
- 自定义 RecycleView
- 自定义Behavior
- 自定义listView + PopuWindows
- 自定义ViewGroup
这几种哪一种是最合适的呢?

分析
  • 首先不看滑动弹出效果,一般来说自定义ListView+自定义ScrollBar是最合适的
  • 自定义 RecycleView 多此一举
  • 自定义Behavior把问题简单复杂话了
  • 自定义scrollView+scrollBar需要重新构造ListView ,重写onDraw,小题大作
  • 自定义ViewGroup 过程太繁琐
  • 如果使用自定义listView + PopuWindows对scrollBar进行设置弹出效果,由于popupWindow是窗体,更不合适是现实出现一个气泡和LISView的scrollBar试试监听的结合。
  • 首先我们确定的是:
    • 自定义ListView
    • 对ScrollBar进行监听和操作
话不多少,还是上代码吧:

MyScrollbarListview.java:

/**
 * 类功能描述:
* * @author yuyahao * @version 1.0

修改时间:
修改备注:
*/
public class MyScrollbarListview extends ListView implements AbsListView.OnScrollListener { private View mScrollPanelView; private int mMeasureWidthSpect ; private int mMeasureHeghtSpect ; /** * 定义y轴的滑动变量,在onScroll里不断去判断和负值 */ private int mScrollbarPanelPosition = 0; private Animation mComeInAnimation = null; private Animation mGoOutAnimation = null; /** * * 定义指示器在Y轴的高度 */ private int mThumbOffset = 0; private int mLastPosition = - 1; private OnPositionListener onPositionListener; public MyScrollbarListview(Context context, AttributeSet attrs) { super(context, attrs); super.setOnScrollListener(this); TypedArray typeArray = context.obtainStyledAttributes(attrs, R.styleable.MyScrollbarListview); int LayoutId = -1,inAnimation = -1,outAnimation = -1; if(typeArray != null){ LayoutId = typeArray.getResourceId(R.styleable.MyScrollbarListview_scrollBarPanel,-1); inAnimation = typeArray.getResourceId(R.styleable.MyScrollbarListview_scrollBarComeInAnamation,-1); outAnimation = typeArray.getResourceId(R.styleable.MyScrollbarListview_scrollBarGoOutAnamation,-1); typeArray.recycle(); } if(inAnimation != -1){ mComeInAnimation = AnimationUtils.loadAnimation(context,inAnimation); }else{ mComeInAnimation = AnimationUtils.loadAnimation(context,R.anim.transation_animation_left); } if(outAnimation != -1){ mGoOutAnimation = AnimationUtils.loadAnimation(context,outAnimation); }else{ mGoOutAnimation = AnimationUtils.loadAnimation(context,R.anim.transation_animation_right); } setMyPanelViewId(LayoutId); int drutionMmillis = ViewConfiguration.getScrollBarFadeDuration();//得到系统默认的淡出的时间 mGoOutAnimation.setDuration(drutionMmillis); mGoOutAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if(mScrollPanelView != null){ mScrollPanelView.setVisibility(GONE); } } @Override public void onAnimationRepeat(Animation animation) { } }); } private void setMyPanelViewId(int layoutId){ mScrollPanelView = LayoutInflater.from(getContext()).inflate(layoutId,this,false); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec);//先测量父容器,在对子布局进行测量 if(mScrollPanelView != null && getAdapter() != null){ measureChild(mScrollPanelView,widthMeasureSpec,heightMeasureSpec); this.mMeasureWidthSpect = widthMeasureSpec; this.mMeasureHeghtSpect = heightMeasureSpec; requestLayout(); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(mScrollPanelView != null){ int left = getMeasuredWidth() - mScrollPanelView.getMeasuredWidth() - mScrollPanelView. getVerticalScrollbarWidth(); mScrollPanelView.layout(left, mScrollbarPanelPosition, left + mScrollPanelView.getMeasuredWidth(), mScrollbarPanelPosition +mScrollPanelView.getMeasuredHeight() ); } } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); //在ViewGroup绘制的事后 if(mScrollPanelView != null && mScrollPanelView.getVisibility() == VISIBLE){ drawChild(canvas,mScrollPanelView,getDrawingTime()); } } @Override public void onScrollStateChanged(AbsListView absListView, int i) { } @Override public void onScroll(AbsListView absListView, int firstItem, int visisbleTotle, int allTotle) { //监听系统滑块在那个位置,设置总结的位置 //监听回调---》去设置位置---》position if(mScrollPanelView != null && onPositionListener != null){ /** * computeHorizontalScrollExtent //滑动条在纵向范围内 自身的高度的幅度--》放大后的 * computeHorizontalScrollOffset //滑动条在纵向 的位置--》放大后的 * computeHorizontalScrollRange //比如0-5000,滑动范围--》放大后的 */ //利用 平行线分线段成比例定理进行 取值 //1.划片的高度 / listView的高度 = computeHorizontalScrollExtent / computeHorizontalScrollRange int height = Math.round(1.0f * computeVerticalScrollExtent()* getMeasuredHeight()/ computeVerticalScrollRange() ); mThumbOffset = (int) (1.0f * computeVerticalScrollOffset() * height/ computeVerticalScrollExtent() ); int left2 = getMeasuredWidth() - mScrollPanelView.getMeasuredWidth() - mScrollPanelView.getVerticalScrollbarWidth(); //2得到 滑块Y正中央的位置Y mThumbOffset = mThumbOffset + height/ 2; mScrollbarPanelPosition = mThumbOffset - height/ 2; mScrollPanelView.layout( left2, mScrollbarPanelPosition, left2 + mScrollPanelView.getMeasuredWidth(), mScrollbarPanelPosition +mScrollPanelView.getMeasuredHeight() ); for (int j = 0; j < getChildCount(); j++) { View view = getChildAt(j); if(view != null){ if(mThumbOffset + height/2 > view.getTop() && mThumbOffset + height/2 < view.getBottom()){ if(mLastPosition != firstItem + j){ mLastPosition = firstItem + j; if(onPositionListener != null){ onPositionListener.myPositionChanged(mLastPosition,null,this,mScrollPanelView); //避免宽度发生改变,重新测量其大小 measureChild(mScrollPanelView,mMeasureWidthSpect,mMeasureHeghtSpect); } } } } } } } @Override protected boolean awakenScrollBars(int startDelay, boolean invalidate) { boolean isWake = super.awakenScrollBars(startDelay, invalidate); if(isWake && mScrollPanelView != null){ if(mScrollPanelView.getVisibility() == GONE){ mScrollPanelView.setVisibility(VISIBLE); if(mComeInAnimation != null){ mScrollPanelView.startAnimation(mComeInAnimation); } } mHandler.removeCallbacksAndMessages(null); mHandler.removeCallbacks(runTask); //设置小时 mHandler.postAtTime(runTask,startDelay+AnimationUtils.currentAnimationTimeMillis()); }else{ mScrollPanelView.setVisibility(GONE); if(mComeInAnimation != null){ mScrollPanelView.startAnimation(mGoOutAnimation); } } return isWake; } private Handler mHandler = new Handler(); private Runnable runTask = new Runnable() { @Override public void run() { if(mGoOutAnimation != null){ mScrollPanelView.startAnimation(mGoOutAnimation); } } }; public interface OnPositionListener{ void myPositionChanged(int position,Student student,MyScrollbarListview myScrollbarListView, View mScrollPanelView); } public void setOnPositionListener(OnPositionListener onPositionListener){ this.onPositionListener = onPositionListener; } }

入口类MainActivity.java


/**
 * 类功能描述:
* * @author yuyahao * @version 1.0

修改时间:
修改备注:
*/
public class MainActivity extends AppCompatActivity { @Bind(R.id.lv_customser_zoomscroll) MyScrollbarListview lv_customser_zoomscroll; private List list = new ArrayList<>(); private ScrollListViewAdapter2 scrollListViewAdapter2; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initData(); } protected void initData() { setContentView(R.layout.activity_main); ButterKnife.bind(this); list.addAll(ServiceData.getStudentList()); lv_customser_zoomscroll.setOnPositionListener(new MyScrollbarListview.OnPositionListener() { @Override public void myPositionChanged(int position, Student student, MyScrollbarListview myScrollbarListView, View mScrollPanelView) { Student student1 = list.get(position); TextView tv = (TextView) mScrollPanelView.findViewById(R.id.iv_name); TextView tv_lessons = (TextView) mScrollPanelView.findViewById(R.id.tv_lessons); tv.setText("" + student1.getName()+" "+" level: "+position); tv_lessons.setText("科目: "+student1.getList().get(0).getPerListenceName()); } }); scrollListViewAdapter2 = new ScrollListViewAdapter2(MainActivity.this,list); lv_customser_zoomscroll.setAdapter(scrollListViewAdapter2); } }

布局.xml:


 <LinearLayout   xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    xmlns:app ="http://schemas.android.com/apk/res/cv.yyh.com.myscrollbarlistview"
    android:layout_height="match_parent">
    <cv.yyh.com.myscrollbarlistview.view.MyScrollbarListview
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:choiceMode="singleChoice"
        android:scrollbarThumbVertical="@drawable/listbar"
        android:id="@+id/lv_customser_zoomscroll"
        app:scrollBarPanel="@layout/panel_text"
        app:scrollBarComeInAnamation="@anim/transation_animation_left"
        app:scrollBarGoOutAnamation="@anim/transation_animation_right"
        />
LinearLayout>

其他代码详见源码地址:https://github.com/androidstarjack/MyScrllBarListView

源码已上传GitHub 连接地址:

https://github.com/androidstarjack/MyScrllBarListView

androidStarjack的博客地址:

http://blog.csdn.net/androidstarjack/article/details/69085140

如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809   

微信公众号:终端研发部

(欢迎关注学习和交流)

你可能感兴趣的:(开发经历,Android总结)