ScrollView反弹效果 仿小米私密短信效果

来源:互联网 发布:网络上粑粑什么意思 编辑:程序博客网 时间:2024/05/18 14:25

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/28441197

现在很多APP都给ScrollView添加了反弹效果,QQ、小米私密短信等。恰好在网上看到一个类:BounceScrollView ,

原创地址是:http://blog.csdn.net/h7870181/article/details/8960430 , 可惜作者没有提供一个效果图,于是我发现小米短信列表页往下拉,有反弹效果,且拉到1/3以上时,会打开私密短信列表,小米的用户可以试试。

我在作者BounceScrollView 类的基础上修改了一下,写了一个例子,给大家分享下。

效果图:(模拟器的效果不佳,凑合可以看出来效果)



1、首先是布局文件:

<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.example.zhy_bouncescrollview02.BounceScrollView        android:background="@drawable/shakehideimg_man"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:id="@+id/id_scrollView" >        <com.example.zhy_bouncescrollview02.MyListView            android:background="#fff"            android:id="@+id/id_listView"            android:layout_width="fill_parent"            android:layout_height="wrap_content" >        </com.example.zhy_bouncescrollview02.MyListView>    </com.example.zhy_bouncescrollview02.BounceScrollView></RelativeLayout>

一个自定义的ScrollView内部包含着一个自定义的ListView,自定义ScrollView是为了添加反弹效果,自定义ListView是为了解决ScrollView和ListView嵌套产生的问题。

2、BounceScrollView

package com.example.zhy_bouncescrollview02;import android.content.Context;import android.graphics.Rect;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.animation.Animation;import android.view.animation.TranslateAnimation;import android.widget.ScrollView;/** * 支持上下反弹效果的ScrollView *  * @author zhy *  */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 * 方法,也应该调用父类的方法,使该方法得以执行. */@Overrideprotected void onFinishInflate(){if (getChildCount() > 0)mView = getChildAt(0);super.onFinishInflate();}@Overridepublic 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();}}

主要就是监听onTouchEvent,当MOVE时,ScrollView中的控件跟随手指移动,UP时恢复原来的位置;当达到1/2时,会调用用户设置的回调,细节就自己看代码了。

3、MyListView

package com.example.zhy_bouncescrollview02;import android.content.Context;import android.util.AttributeSet;import android.widget.ListView;/** * 解决ScrollView与ListView的嵌套问题 * @author zhy *  */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);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){/** * 解决ScrollView与ListView的嵌套问题 */int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);}}

4、主Activity

package com.example.zhy_bouncescrollview02;import java.util.ArrayList;import java.util.Arrays;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import com.example.zhy_bouncescrollview02.BounceScrollView.Callback;public class MainActivity extends Activity{private ListView mListView;private BounceScrollView mScrollView;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mScrollView = (BounceScrollView) findViewById(R.id.id_scrollView);mScrollView.setCallBack(new Callback(){@Overridepublic void callback(){Toast.makeText(MainActivity.this, "you can do something!", 0).show();Intent intent = new Intent(MainActivity.this,SecondActivity.class);startActivity(intent);overridePendingTransition(R.anim.fade_in, R.anim.fade_out);}});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"))));}}

MainActivity代码也很简单,初始化两个控件,设置了下ScrollView的Callback。



好了,好几天没写代码了,就这样吧。


源码点击下载








18 2