转载请著名出处: 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