先放一个效果图:
好了,看见这个效果,想知道怎么实现吗,一起来看看吧
一 类继承Listview
/** * * 继承式控件,覆写构造方法, * 覆写overScrollBy方法 * 暴露方法,去得到外界的ImageView,测量ImageView的高度 * 覆写onTouchEvent方法 * 代码实现 */ public class ParallaxListView extends ListView{ private int drawableHeight; private ImageView fangfa; private int orignalHeight; //重写三个方法 public ParallaxListView(Context context) { this(context,null); } public ParallaxListView(Context context, AttributeSet attrs) { this(context,attrs,0); } public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //定义一个方法 public void setFangfa(ImageView fangfa) { this.fangfa = fangfa; //获取图片的原始高度 drawableHeight = fangfa.getDrawable().getIntrinsicHeight(); //获取 imageview 的原始高度以便回弹 orignalHeight = fangfa.getHeight(); } //重写,滑动到listview两端时被回调 //重要参数 deltay isTouchEvent /** * 当滑动的超出上,下,左,右最大范围时回调 * * @param deltaX x方向的瞬时偏移量,左边到头,向右拉为负,右边到头,向左拉为正 * @param deltaY y方向的瞬时偏移量,顶部到头,向下拉为负,底部到头,向上拉为正 * @param scrollX 水平方向的永久偏移量 * @param scrollY 竖直方向的永久偏移量 * @param scrollRangeX 水平方向滑动的范围 * @param scrollRangeY 竖直方向滑动的范围 * @param maxOverScrollX 水平方向最大滑动范围 * @param maxOverScrollY 竖直方向最大滑动范围 * @param isTouchEvent 是否是手指触摸滑动, true为手指, false为惯性 * @return */ @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { //顶部下拉,用户触摸操作才执行视差效果 if(deltaY<0 && isTouchEvent){ //将deltay的负值改为绝对值,赋给控件图,达到视差效果 int newHeight = (int) (fangfa.getHeight() + Math.abs(deltaY)); //把新的高度付给控件 fangfa.getLayoutParams().height = newHeight; //解决图无线发达的问题,不能超过本身高度 if(newHeight<=drawableHeight){ fangfa.getLayoutParams().height = newHeight; fangfa.requestLayout(); } } return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); } //重写方法 @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()){ //手指抬起时执行一系列操作 case MotionEvent.ACTION_UP: int currentHeight = fangfa.getHeight(); //属性动画 final ValueAnimator animator = ValueAnimator.ofInt(currentHeight, orignalHeight); //动画更新监听 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float fraction = animator.getAnimatedFraction(); //获取中间值 ,赋给控件新高度 Integer animatedValue = (Integer)animator.getAnimatedValue(); //使新的高度生效 fangfa.getLayoutParams().height = animatedValue; fangfa.requestLayout(); } }); //动画的回弹效果,值越大,回弹的越厉害 animator.setInterpolator((new OvershootInterpolator(1))); //设置动画执行时间 animator.setDuration(500); animator.start(); break; } return super.onTouchEvent(ev); } }
二 去MainActivity 的Xml文件布局
<com.example.myapplication.ParallaxListViewandroid:id="@+id/plv" android:scaleType="centerCrop" !!重要属性 android:layout_width="match_parent" android:layout_height="match_parent"> </com.example.myapplication.ParallaxListView>
三 MainActivity
public class MainActivity extends AppCompatActivity { private ParallaxListView plv; private ImageView image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //控件id plv = (ParallaxListView) findViewById(R.id.plv); //给lisview添加一个头布局文件,布局变成对象 View headerView = View.inflate(this, R.layout.header, null); //头部控件id image = (ImageView) headerView.findViewById(R.id.image); //添加头部布局 plv.addHeaderView(headerView); //等View界面全部绘制完毕后,去得到已经绘制的宽和高 image.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { plv.setFangfa(image); //释放资源 image.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); //使用Lisrview的ArrayAdapter添加文本的item //给listview设置数据 plv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,Chess.NAMES)); } }
四 头部布局
<ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="165dp" android:scaleType="centerCrop" android:src="@drawable/a99"/> !!图片自己找
五 定义了一个类,为ListView添加数据
public class Chess { public static final String[] NAMES = new String[]{"宋江", "卢俊义", "吴用", "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深", "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘", "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍", " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪", "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方", "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充", "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿", "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩", "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立", "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜", "时迁", "段景柱"};
这样就可以做出一个视差特效的效果,可以应用在很多地方,写的可能不太好,请
大神多多指教。