弹性ScrollView下拉弹性显示底部内容的简单实现

今天写了ScrollView的下拉,弹性显示底部内容继续加载的例子,之所以不用ListView是因为ListView基本只能一列,不好实现瀑布流效果,而ScrollView基本没什么限制,所以就简单实现了一下ScrollView的相同效果,看了网上的很多相似的做法,写得确实很不错,不过看起来还是比较费劲的,本人新手,尽量就按照自己的理解,简易的实现了一下,东西内容不多,就显示和隐藏的一般逻辑,没有太多界面上复杂的东西首先,个人实现的原理,原理也很简单,就是重写ScrollView的OnTouchEvent方法来实现对ScrollView,触屏事件的监听把"继续加载"的View放在下方,设置BottomPadding为负的View高度,所以一开始就不显示了当滚动到ScrollView的子View显示完后,再不断的设置"继续加载View"的BottomPadding,于是"继续加载View"就能不断显示了,将该VIew不断隐藏也是同样的原理。主要的实现类
public class LaScrollView extends ScrollView implements ShowHide {

	LinearLayout llController, llRefresh;
	LinearLayout llContent;

	// llContent是否滚到底
	boolean isBottom;

	int svHeight;
	int llControllerHeight;
	int llRefreshHeight;
	
	TextView tvView;
	LaScrollView sv = this;

	// 是否可以进行加载
	boolean continueLoad = false;

	public void init() {
		measureView(llController);
		measureView(llRefresh);
		llControllerHeight = llController.getMeasuredHeight();
		llRefreshHeight = llRefresh.getMeasuredHeight();
		showHide(0, false);
	}

	public LaScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	// 估计/计算View的高度
	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}

		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	float y;
	public boolean onTouchEvent(MotionEvent event) {
		float curY = event.getY();
		float moveY; // 等于 curY - y; 负数表示手指向上 ,正数表示手指向下
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			y = curY;
			break;
		case MotionEvent.ACTION_MOVE:
			moveY = curY - y;
			Log.v("moveY ", "" + moveY);
			if (moveY < 0) {// 向上滑动,有可能要显示隐藏的VIew
				if (sv.getHeight() + sv.getScrollY() == llController
						.getHeight()) {
					isBottom = true;
				}
			}

			if (isBottom) { // llContent滚到底端
				if (moveY > 0) { // 慢慢隐藏
					showHide((int) (-moveY - 1), true);
				} else {// 有可能会拉出隐藏View
					showHide((int) (-moveY), true);
				}
			}
			y = curY;
			break;
		case MotionEvent.ACTION_UP:
			y = curY;
			if (continueLoad) {// 可以加载状态下松手
				TextView child = new TextView(getContext());
				showHide(0, false);
				child.setText("我是新来的");
				llContent.addView(child);
				continueLoad = false;
			} else {
				showHide(0, false);
			}
			tvView.setText("向上拖动进行加载");
			break;
		}
		return super.onTouchEvent(event);
	};

	@Override
	public void showHide(int move, boolean isShow) {
		// TODO Auto-generated method stub
		if (isShow) {
			llRefresh.setVisibility(View.VISIBLE);
			int olePadding = llRefresh.getPaddingBottom();
			int newPadding = olePadding + move;
			Log.v("new Padding ", " move " + move + "  \n" + newPadding);

			if (move > 0) {// 不断显示
				if (newPadding > 0) {
					llRefresh.setPadding(0, 0, 0, 0);
				} else {
					if (((float) (llRefreshHeight + newPadding))
							/ llRefreshHeight > 0.9) {// 设置什么时候可以刷新条件自己定
						tvView.setText("放手继续加载");
						continueLoad = true;

					}
					llRefresh.setPadding(0, 0, 0, newPadding);
				}
			} else {// 不停隐藏
				int neHeight = -llRefreshHeight;
				if (newPadding < neHeight) {
					llRefresh.setPadding(0, 0, 0, neHeight);
					isBottom = false;
				} else {
					if (((float) (llRefreshHeight + newPadding))
							/ llRefreshHeight < 0.9) {// 设置什么时候可以刷新条件自己定
						tvView.setText("向上拖动进行加载");
						continueLoad = false;

					}
					llRefresh.setPadding(0, 0, 0, newPadding);
				}
			}

		} else {
			llRefresh.setPadding(0, 0, 0, -llRefreshHeight);
		}
	}

	public void setLlController(LinearLayout llController) {
		this.llController = llController;
	}

	public void setLlContent(LinearLayout llContent) {
		this.llContent = llContent;
	}

	public void setLlRefresh(LinearLayout llRefresh) {
		this.llRefresh = llRefresh;
	}

	public void setTvView(TextView tvView) {
		this.tvView = tvView;
	}
}

interface ShowHide {
	public void showHide(int move, boolean isShow);
}

主要的加载Activity,内容不多

public class MainActivity extends Activity {

	LayoutInflater inflater;
	LaScrollView sv;
	LinearLayout llController,llRefresh;
	LinearLayout llContent;
	TextView tvView;
	//是否滚到底
	boolean isBottom;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		setup();
	}

	private void setup(){
		inflater = LayoutInflater.from(this);
		sv = (LaScrollView) findViewById(R.id.sv);
		llController = (LinearLayout) findViewById(R.id.llComtroller);
		llContent = (LinearLayout) findViewById(R.id.llContent);
		llRefresh = (LinearLayout) findViewById(R.id.refreshLayout);
		tvView = (TextView) findViewById(R.id.head_tipsTextView);
		
		//为了看起来简洁,更好阅读, 界面十分简易
		for (int i = 0; i < 40; i++) {
			TextView tv = new TextView(this);
			tv.setText("哈哈哈哈啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊");
			llContent.addView(tv);
		}
		
		//把sv和相关控件联系起来
		sv.setLlContent(llContent);
		sv.setLlController(llController);
		sv.setLlRefresh(llRefresh);
		sv.setTvView(tvView);
		sv.init();
	}
	

}

界面xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.example.android_test.component.LaScrollView
        android:id="@+id/sv"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
        <LinearLayout
            android:id="@+id/llComtroller"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" >

            <LinearLayout
                android:id="@+id/llContent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="vertical" >
            </LinearLayout>

            <include 
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                layout="@layout/list_bottom"/>
        </LinearLayout>
    </com.example.android_test.component.LaScrollView>

</RelativeLayout>

实现过程还是比较简单的, 代码都在这了 , 没什么其他内容了 ,  源程序在 这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值