前几天看到有好多人搞了一个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:
/**
* 类功能描述:</br>
*
* @author yuyahao
* @version 1.0 </p> 修改时间:</br> 修改备注:</br>
*/
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
/**
* 类功能描述:</br>
*
* @author yuyahao
* @version 1.0 </p> 修改时间:</br> 修改备注:</br>
*/
public class MainActivity extends AppCompatActivity {
@Bind(R.id.lv_customser_zoomscroll)
MyScrollbarListview lv_customser_zoomscroll;
private List<Student> 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:
<?xml version="1.0" encoding="utf-8" ?>
<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
微信公众号:终端研发部
(欢迎关注学习和交流)