这个效果和网易彩票安卓客户端的双色球主页下拉效果差不多。公司也是做彩票的,想要一个这样的效果。开始有思路,但是实现起来还是挺麻烦的,逻辑不好理,经过一番研究,果然不负有心人。终于完美实现。分享给大家......
默认效果:
向下滑动后:
这里其实有很多细节,比如下滑高度小于卷帘的1/2,就弹回原处,大于1/2就自动弹到底,有一个弹性的效果。
当然上滑的时候也是,滑动距离小于1/2,还是留在底部,大于1/2,就弹回最顶部。
当你一进来,不下拉,就不会弹出卷帘,往上滑的时候就会滑动下面的内容,再次往下滑动,也不会弹出卷帘,而是要释放,再滑动一次,这样可以明显知道卷帘和下面的不是连在一起的。
布局文件代码:
主类Activity代码很简单:
package com.myrollerscrollview.activity;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.widget.TextView;
import com.myrollerscrollview.R;
import com.myrollerscrollview.listener.MyScrollViewListener;
import com.myrollerscrollview.view.MyScrollView;
//主界面
public class MainActivity extends Activity implements MyScrollViewListener {
private MyScrollView scrllon_view;
private TextView lisi_textview;
private TextView main_textview;
private TextView main_textview1;
private TextView main_textview2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
setContentView(R.layout.activity_main);
scrllon_view = (MyScrollView) findViewById(R.id.main_scrollview);
lisi_textview = (TextView) findViewById(R.id.lisi_textiview);
main_textview = (TextView) findViewById(R.id.main_textiview);
main_textview1 = (TextView) findViewById(R.id.main_textiview1);
main_textview2 = (TextView) findViewById(R.id.main_textiview2);
scrllon_view.setMaxHeight(350);
scrllon_view.topView = this.lisi_textview;
}
@Override
public void onScrollChanged(MyScrollView scrollView, int x, int y, int oldx, int oldy) {
//System.out.println("x=" + x + " y=" + y + " oldx=" + oldx + " oldy=" + oldy);
}
}
package com.myrollerscrollview.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;
import com.myrollerscrollview.listener.MyScrollViewListener;
/**
* 自定卷帘Scrollview
*
* @author lengguoxing
*
* 引用地址:com.myrollerscrollview.view.MyScrollView
*/
public class MyScrollView extends ScrollView {
private MyScrollViewListener scrollViewListener = null;
private MyScrollView myScrollView = this;
public View topView;//顶部卷帘
public boolean isTopViewAllGone = true;//卷帘完全隐藏
private int downMoveDistance = 0;// 向下滑动的距离
private int upMoveDistance = 0;// 滑动到底时,向上滑动的距离
public int maxHeight = 100;//这个是可以用户通过方法setMaxHeight自定义的
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(MyScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
public int getMaxHeight() {
return maxHeight;
}
public void setMaxHeight(int maxHeight) {
this.maxHeight = maxHeight;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null ) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
int downY = 0;// 按下时候焦点的y坐标
int moveY = 0;// 滑动时候存储焦点的y坐标
int upY = 0;// 释放时候焦点的y坐标
int downScrollY = 0;//滑动开始时滚动条的Y坐标
android.widget.LinearLayout.LayoutParams lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, 0);
/**
*
* topView.getBottom() - topView.getTop() == maxHeight 卷帘完全显示的判断
* topView.getBottom() == topView.getTop() 卷帘完全隐藏的判断
* myScrollView.getScrollY()==0可以判断是否滚动了。
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
//System.out.println("onTouchEvent----------------------getHeight=" + this.getHeight() + " ");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN://按下的时候
//System.out.println("----------------action down=(" + event.getX() +", " + event.getY() + ")");
downY = (int) event.getY();
downScrollY = myScrollView.getScrollY();
//upMoveDistance = downMoveDistance;
upMoveDistance = 0;
return super.onTouchEvent(event);
case MotionEvent.ACTION_MOVE://滑动的时候
//System.out.println("----------------action move=(" + event.getX() +", " + event.getY() + ")");
//System.out.println("----------------myScrollView " + myScrollView.getTop() + " " + myScrollView.getBottom());
//System.out.println("---------------------topView " + topView.getTop() + " " + topView.getBottom());
//System.out.println("-----myScrollView.getScrollY " + myScrollView.getScrollY() + " maxheight=" + maxHeight);
//System.out.println("-----------------downMoveDistance= " + downMoveDistance + " upMoveDistance=" + upMoveDistance);
if(topView.getBottom() - topView.getTop() == maxHeight){//卷帘完全显示
downMoveDistance = maxHeight;
upMoveDistance = 0;
}
if(topView.getBottom() == topView.getTop()){//卷帘完全隐藏
isTopViewAllGone = true;
downMoveDistance = 0;
upMoveDistance = maxHeight;
}else{
isTopViewAllGone = false;
}
moveY = (int) event.getY();
int YY = moveY - downY;
if (YY > 0) {// 向下滑动
int tempMove = (moveY - downY) % maxHeight;
if (tempMove > downMoveDistance) {
downMoveDistance = tempMove;
}
if (downMoveDistance > 0) {
//向下滑的条件是:1、未滚动到底;2、滚动条还在顶部;3、滚动条本来就在顶部
if (downMoveDistance <= maxHeight && myScrollView.getScrollY() == 0 && downScrollY == 0) {
lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, downMoveDistance);
lp.setMargins(0, 0, 0, 0);
topView.setPadding(0, 0, 0, 0);
topView.setLayoutParams(lp);
}
}
} else if (YY < 0 && downMoveDistance > 0) {// 向上滑动 //这里的逻辑有点问题
int tempMove = (downY - moveY) % maxHeight;
if (tempMove > upMoveDistance) { // 这里有问题
upMoveDistance = tempMove;
}
if (upMoveDistance > 0) {
if (upMoveDistance < maxHeight && myScrollView.getScrollY() == 0) {
lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, downMoveDistance - upMoveDistance);
lp.setMargins(0, 0, 0, 0);
topView.setPadding(0, 0, 0, 0);
topView.setLayoutParams(lp);
}
}
}
if(isTopViewAllGone){
return super.onTouchEvent(event);
}else{
return false;
}
case MotionEvent.ACTION_UP:
//System.out.println("----------------action up=(" + event.getX() +", " + event.getY() + ")");
upY = (int) event.getY();
int YY2 = (upY - downY);
if (YY2 > 0) {// 向下滑动
if (YY2 < maxHeight / 2 && myScrollView.getScrollY() == 0 && downScrollY == 0) {// 滑动距离小于一半,自动弹回原处
lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, 0);
topView.setLayoutParams(lp);
downMoveDistance = 0;
} else if (YY2 >= maxHeight / 2 && myScrollView.getScrollY() == 0 && downScrollY == 0) {// 滑动距离大于一半,加速最底部
lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, maxHeight);
topView.setLayoutParams(lp);
downMoveDistance = maxHeight;
}
} else if (YY2 < 0) {// 向上滑动
YY2 = -YY2;//
if (YY2 < maxHeight / 2 && myScrollView.getScrollY() == 0) {// 向上滑动距离小于一半,自动弹回最底部
lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, maxHeight);
topView.setLayoutParams(lp);
downMoveDistance = maxHeight;
upMoveDistance = 0;
} else if (YY2 >= maxHeight / 2 && myScrollView.getScrollY() == 0) {// 向上滑动距离大于一半,加速原处
lp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, 0);
topView.setLayoutParams(lp);
downMoveDistance = 0;
upMoveDistance = maxHeight;
}
}
return super.onTouchEvent(event);
}
return super.onTouchEvent(event);
}
}
MotionEvent.ACTION_MOVE 控制滑动效果
MotionEvent.ACTION_UP 控制弹性效果
这里的几个判断很重要:
topView.getBottom() - topView.getTop() == maxHeight 卷帘完全显示的判断
topView.getBottom() == topView.getTop() 卷帘完全隐藏的判断
myScrollView.getScrollY()==0可以判断是否滚动了。
里面的注释很详细,就不一一介绍了。这里附上下载的地址 点击打开链接