ScrollView 反弹效果
现在很多APP都给ScrollView添加了反弹效果,QQ、小米私密短信等。恰好在网上看到一个类:BounceScrollView ,
原创地址是:http://blog.csdn.net/h7870181/article/details/8960430 , 可惜作者没有提供一个效果图,于是我发现小米短信列表页往下拉,有反弹效果,且拉到1/3以上时,会打开私密短信列表,小米的用户可以试试。
我在作者BounceScrollView 类的基础上修改了一下,写了一个例子,给大家分享下。
效果图:(模拟器的效果不佳,凑合可以看出来效果)
布局文件main.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" > <com.topcsa.test_android3.BounceScrollView android:id="@+id/id_scrollView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/ic_launcher" > <com.topcsa.test_android3.MyListView android:id="@+id/id_listView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#fff" > </com.topcsa.test_android3.MyListView> </com.topcsa.test_android3.BounceScrollView> </RelativeLayout>
BounceScrollView.java:
public class BounceScrollView extends ScrollView { private boolean isCalled; private Callback mCallback; /** * 包含的View */ private View mView; /** * 存储正常时的位置 */ private Rect mRect = new Rect(); /** * y坐标 */ private int y; private boolean isFirst = true; public BounceScrollView(Context context, AttributeSet attrs) { super(context, attrs); } /*** * 根据 XML 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. 即使子类覆盖了 onFinishInflate * 方法,也应该调用父类的方法,使该方法得以执行. */ @Override protected void onFinishInflate() { if (getChildCount() > 0) mView = getChildAt(0); super.onFinishInflate(); } @Override public boolean onTouchEvent(MotionEvent ev) { if (mView != null) { commonOnTouch(ev); } return super.onTouchEvent(ev); } private void commonOnTouch(MotionEvent ev) { int action = ev.getAction(); int cy = (int) ev.getY(); switch (action) { case MotionEvent.ACTION_DOWN: break; /** * 跟随手指移动 */ case MotionEvent.ACTION_MOVE: int dy = cy - y; if (isFirst) { dy = 0; isFirst = false; } y = cy; if (isNeedMove()) { if (mRect.isEmpty()) { /** * 记录移动前的位置 */ mRect.set(mView.getLeft(), mView.getTop(), mView.getRight(), mView.getBottom()); } mView.layout(mView.getLeft(), mView.getTop() + 2 * dy / 3, mView.getRight(), mView.getBottom() + 2 * dy / 3); if (shouldCallBack(dy)) { if (mCallback != null) { if (!isCalled) { isCalled = true; resetPosition(); mCallback.callback(); } } } } break; /** * 反弹回去 */ case MotionEvent.ACTION_UP: if (!mRect.isEmpty()) { resetPosition(); } break; } } /** * 当从上往下,移动距离达到一半时,回调接口 * * @return */ private boolean shouldCallBack(int dy) { if (dy > 0 && mView.getTop() > getHeight() / 2) return true; return false; } private void resetPosition() { Animation animation = new TranslateAnimation(0, 0, mView.getTop(), mRect.top); animation.setDuration(200); animation.setFillAfter(true); mView.startAnimation(animation); mView.layout(mRect.left, mRect.top, mRect.right, mRect.bottom); mRect.setEmpty(); isFirst = true; isCalled = false; } /*** * 是否需要移动布局 inner.getMeasuredHeight():获取的是控件的总高度 * * getHeight():获取的是屏幕的高度 * * @return */ public boolean isNeedMove() { int offset = mView.getMeasuredHeight() - getHeight(); int scrollY = getScrollY(); // 0是顶部,后面那个是底部 if (scrollY == 0 || scrollY == offset) { return true; } return false; } public void setCallBack(Callback callback) { mCallback = callback; } interface Callback { void callback(); } }
MyListView.java:
package com.topcsa.test_android3; import android.content.Context; import android.util.AttributeSet; import android.widget.ListView; public class MyListView extends ListView { public MyListView(Context context, AttributeSet attrs) { super(context, attrs); } public MyListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public MyListView(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 解决ScrollView与ListView的嵌套问题 */ int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
MainActivity.java:
package com.topcsa.test_android3; import java.util.ArrayList; import java.util.Arrays; import com.topcsa.test_android3.BounceScrollView.Callback; import android.app.Activity; import android.app.ActionBar; import android.app.Fragment; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import android.os.Build; public class MainActivity extends Activity { private ListView mListView; private BounceScrollView mScrollView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mScrollView = (BounceScrollView) findViewById(R.id.id_scrollView); mScrollView.setCallBack(new Callback() { public void callback() { Toast.makeText(MainActivity.this, "you can do something!", 0) .show(); } }); mListView = (ListView) findViewById(R.id.id_listView); mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>( Arrays.asList("Hello", "World", "Welcome", "Java", "Android", "Lucene", "C++", "C#", "HTML", "Welcome", "Java", "Android", "Lucene", "C++", "C#", "HTML")))); } }
运行即可。
源码下载地址:源码下载
本文转载自:http://blog.csdn.net/lmj623565791/article/details/28441197
作者:af74776
文章出处:http://www.cnblogs.com/scetopcsa/
欢迎关注微信公众号:yilu_yiyou(一路一游),一个不仅仅是代码的世界!
如果文中有什么错误,欢迎指出。以免更多的人被误导。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
文章出处:http://www.cnblogs.com/scetopcsa/
欢迎关注微信公众号:yilu_yiyou(一路一游),一个不仅仅是代码的世界!
如果文中有什么错误,欢迎指出。以免更多的人被误导。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。