简单视察特效的实现

实现的效果:

这个是一个ListrView,头部添加一张图片,在下拉时,图片会全部显示出来,松开以后图片还会回弹到原来的位置;

下面直接代码:

ParallaxListView:

/**
 * Created by peiyan on 2017/8/16.
 * 继承式控件:
 * 1.继承ListView,覆写构造方法
 * 2.覆写overScrollBy方法,重点关注deltaY,isTouchEvent方法
 * 3.暴露一个方法,去得到外界ImageView,并测量ImageView控件的高度
 * 4.覆写onTouchEvent方法
 */
public class ParallaxListView extends ListView {
    private ImageView header;
    private int intrinsicHeight;
    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 setHeader(ImageView header) {
        this.header = header;
        //获取图片的原始高度
        intrinsicHeight = header.getDrawable().getIntrinsicHeight();
          //获取imageView的原始高度
        orignalHeight = header.getHeight();

    }


    /**
     * 重点:滑动到ListView两端的时候被调用(上部和底部)
     * @param deltaX
     * @param deltaY 竖直方向滑动的瞬时变化量,顶部下拉为-,底部上拉为+;
     * @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) {
        //通过Log来验证参数的作用
        //deltaY=-270;  scrollY=0滚动; scrollRangeY=0滚动范围; maxOverScrollY=0最大滚动; isTouchEvent=true是触摸事件;
        Log.d("PY","deltaY"+deltaY+
                "isTouchEvent"+isTouchEvent);
        //顶部下拉,用户触摸的操作才执行视差效果
        if (deltaY<0 && isTouchEvent==true){
            //deltaY是一个负值,我们要改为绝对值 Math.abs(deltaY),累计给我们的header高度
            int newHeight = header.getHeight() + Math.abs(deltaY);
      //避免图片无限放大,图片最大不能超过图片本身的高度
            //在上面的方法里拿到图片的原始高度
            if (newHeight<=intrinsicHeight){
                //把新的高度值赋值给控件,改变控件的高度
                header.getLayoutParams().height=newHeight;
                header.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 = header.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();
                    //让新的高度值生效
                       header.getLayoutParams().height=animatedValue;
                       header.requestLayout();
                   }
               });
                //动画的回弹效果。值越大,回弹效果越明显
                animator.setInterpolator(new OvershootInterpolator(2));
                //设置动画执行时间
                animator.setDuration(3000);
                //执行动画
                    animator.start();
        }
        return super.onTouchEvent(ev);
    }
}

chinaese:(自己定义放数据的类)
public class chinaese {
    public static final String[] NAMES = new String[]{"宋江", "卢俊义", "吴用",
            "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
            "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
            "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
            " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
            "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
            "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
            "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
            "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
            "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
            "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
            "时迁", "段景柱"};


}


MainActivity:

/**
 * 视差特效实现思路:(两种)
 * 1.解析ontouche,Action_Down,Action_move,Action_up;业务逻辑过于复杂
 * (用第二种)
 * 2.重写ListView的ouverScrollBy方法,继承式自定义控件ListView,根据用户下拉的距离
 * 动态修改headerView的高度;
 * 在MainActivity中的实现思路:
 * a.拷贝文本资源到项目中,自定义控件继承ListView
 * b.使用自定义控件,并往头部添加布局,设置适配器
 * c.使用视图树,把ImageView传给我们的自定义控件;
 */
public class MainActivity extends AppCompatActivity {

    private ParallaxListView plv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        //listView添加一个头布局
        View headerView= View.inflate(this, R.layout.layout_header, null);
        plv.addHeaderView(headerView);
        final ImageView header = (ImageView) headerView.findViewById(R.id.header);
         //等View界面全部绘制完毕的时候,去得到已经绘制完控件的宽和高;
        header.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
              @Override
              public void onGlobalLayout() {
                  //宽和高已经测量完毕
                  plv.setHeader(header);
                  //释放资源
                  header.getViewTreeObserver().removeGlobalOnLayoutListener(this);

              }
          });
        //使用ListView的ArrayAdapter,添加文本item
        plv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,chinaese.NAMES));
    }

    private void initView() {
        plv = (ParallaxListView) findViewById(R.id.plv);
    }
}

下面是布局:

activity_main:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/activity_main"
    android:layout_width="match_parent" android:layout_height="match_parent"
  >
<com.example.myshichatexiaodemo.View.ParallaxListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/plv"/>
</RelativeLayout>
layout_header:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:id="@+id/header"
        android:src="@drawable/parallax_img"
        android:scaleType="centerCrop"
        />

</LinearLayout>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值