转载请著名出处:
http://blog.csdn.net/forwardyzk/article/details/46636997
我们知道XLIstview有上拉刷新和下拉加载,现在模拟一下XlistView的下拉刷新,使Scroller也有标题,通过滑动控制标题的显示和隐藏.
我们先来看一下效果:
首先创建标题View
scroller_header.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/darker_gray"> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:gravity="center_vertical" android:text="我是第一个孩子" android:textSize="25sp" /> </LinearLayout>
自定义标题控件
public class ScrollHeader extends LinearLayout { private LinearLayout mContainer; private Context mContext; public ScrollHeader(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; initView(); } private void initView() { // 初始情况 LayoutParams lp = new LayoutParams( android.view.ViewGroup.LayoutParams.FILL_PARENT, 0); mContainer = (LinearLayout) LayoutInflater.from(mContext).inflate( R.layout.scroller_header, null); addView(mContainer, lp); setGravity(Gravity.BOTTOM); } /** * 设置显示的高度 * * @param height */ public void setVisiableHeight(int height) { if (height < 0) height = 0; LayoutParams lp = (LayoutParams) mContainer .getLayoutParams(); lp.height = height; mContainer.setLayoutParams(lp); } /** * 获取显示的高度 * * @return */ public int getVisiableHeight() { return mContainer.getHeight(); } }
开始默认设置mContainer的高度为0,就是默认的不显示,
setVisiableHeight动态设置标题的高度
getVisiableHeight获取标题的高度
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.example.yang.listviewtitle.view.MyScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.example.yang.listviewtitle.view.ScrollHeader android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第2个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第3个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第4个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第5个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第6个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第7个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第8个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第9个孩子" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginBottom="10dp" android:background="@android:color/holo_blue_dark" android:gravity="center_vertical" android:padding="10dp" android:text="我是第10个孩子" /> </LinearLayout> </com.example.yang.listviewtitle.view.MyScrollView> </LinearLayout>
这里面使用了自定义的ScrollerView和在自定义的ScrollerView中使用了自定义的标题,这里要注意的是:
1.MyScrllerView的子View是Linearlayout,如果要换成其他的布局,要在代码中做相应的改变
2.要把自定义的标题作为MyScrllerView子View的第一个子View.
自定义MyScrollerView
public class MyScrollView extends ScrollView { private ScrollHeader mHeader; private float mLastY = -1; private Context mContext; private int MAX_VISI_HEIGHT; private Scroller mScroller; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; MAX_VISI_HEIGHT = getScreenHeight() / 3; mScroller = new Scroller(context, new DecelerateInterpolator()); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取Scroller的第一个孩子,就是包裹所有孩子的View LinearLayout firstLL = (LinearLayout) getChildAt(0); mHeader = (ScrollHeader) firstLL.getChildAt(0); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent ev) { if (mLastY == -1) { mLastY = ev.getRawY(); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: final float deltaY = ev.getRawY() - mLastY; mLastY = ev.getRawY(); if (deltaY > 0) { int height = mHeader.getVisiableHeight(); if (MAX_VISI_HEIGHT > height) { //更新header高度 mHeader.setVisiableHeight((int) deltaY + height); } } break; case MotionEvent.ACTION_UP: Log.d("MyScrollerView", "MOVE_UP"); if (mHeader.getVisiableHeight() > 0) { resetHeaderHeight(); } break; } return super.onTouchEvent(ev); } /** * 获取屏幕的高度 * * @return */ private int getScreenHeight() { WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics displayMetrics = new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.heightPixels; } private void resetHeaderHeight() { int height = mHeader.getVisiableHeight(); Log.d("MyScrollerView", "移动的高度:" + (0 - height)); mScroller.startScroll(0, height, 0, 0 - height, 400); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { mHeader.setVisiableHeight(mScroller.getCurrY()); postInvalidate(); } super.computeScroll(); } }
设计思路:
1.获取到不局文件中的标题View
2.通过监听滑动ScrllerView手势,如果是向下拉,那么计算出滑动的距离,
3.讲滑动的距离来移动标题View
4.当手离开了屏幕,那么使用Scroller来平移标题View到初始的位置
在onMeasure中获取要操作的标题View
//获取Scroller的第一个孩子,就是包裹所有孩子的View LinearLayout firstLL = (LinearLayout) getChildAt(0); mHeader = (ScrollHeader) firstLL.getChildAt(0);
在onTouchEvent的MotionEvent.MOVE_MOVE中计算出滑动的具体,动态设置标题View的高度
在onTouchEvent的MotionEvent.MOVE_UP:设置标题的回到初始的位置
mScroller.startScroll(0, height, 0, 0 - height, 400); invalidate();
在computeScroll()方法中动态的设置标题View的高度,否则就不会有平移的效果.
@Override public void computeScroll() { if (mScroller.computeScrollOffset()) { mHeader.setVisiableHeight(mScroller.getCurrY()); postInvalidate(); } super.computeScroll(); }
滑动距离的判断:不能操作屏幕的三分之一的高度,这个高度可以根据需求来改变
回弹的时间:现在设置的400毫秒,这个时间可以根据需求来改变.
最主要的标题的显示:需更改变,只需更改scroller_header.xml布局.
到此效果已经实现.
源码下载:http://download.csdn.net/detail/forwardyzk/8838455