码迷,mamicode.com
首页 > 移动开发 > 详细

Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现

时间:2018-05-12 19:29:56      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:world   undle   自动   super   get   天津   pre   coding   tde   

  滑动ListView列表然后 listView上边的视图 跟随着上拉或者下拉的距离 自动放大或者缩小  视图里边元素自动平移的效果

技术分享图片

 

思路很简单

根据listView 的滑动距离去计算图片和文字应该平移的距离

例如顶部视图本来高度为500px  我们定义视图收缩到200px为最小高度,那么视图向上滑动的最大距离就为300px

当我们将列表向上滑动300px的时候试图就应该滑到最小高度了   继续上滑,不继续缩小视图高度即可

同理 下拉的时候 下拉300px 此时视图应该从200px高度变为500px高度  继续下拉 不增加试图高度即可

简单来说就是对 触摸事件的处理  根据   (上拉或者下拉的距离)/300px = 视图应该缩小或者放大的比例

上代码:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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:background="#fff"
    >

    <RelativeLayout
        android:id="@+id/rl_head"
        android:layout_width="match_parent"
        android:layout_height="300px"
        android:text="Hello World!"
        android:background="#9F79EE">

        <ImageView
            android:id="@+id/iv_head"
            android:layout_marginTop="60px"
            android:layout_marginLeft="50px"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@mipmap/ic_launcher_round"
            />

        <TextView
            android:id="@+id/tv_name"
            android:layout_marginTop="80px"
            android:layout_marginLeft="180px"
            android:text="一个名称"
            android:textColor="#fff"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/tv_other"
            android:text="其他字段"
            android:textColor="#fff"
            android:layout_marginTop="200px"
            android:layout_marginLeft="50px"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        </RelativeLayout>


    <ListView
        android:id="@+id/lv"
        android:layout_below="@id/rl_head"
        android:listSelector="@android:color/transparent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

 

MainActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.Arrays;
import java.util.List;

public class MainActivity extends Activity {

    private ListView listView;
    private RelativeLayout rl_head;
    private ImageView iv_head;
    private TextView tv_name,tv_other;

    private MyAdapter adapter;

    //*******************************
    private int mLastY = 0;  //最后的点
    private static int mNeedDistance;   // 需要滑动的距离
    private static int mMinHight; //最小高度
    private static int mOrignHight; //原始的高度

    private int mCurrentDistance = 0;  //当前的距离
    private float mRate = 0;  //距离与目标距离的变化率 mRate=mCurrentDistance/mNeedDistance
    private int mPhotoOriginHeight; //图片的原始高度
    private int mPhotoOriginWidth; //图片的原始宽度
    private int mPhotoLeft;  //图片距左边的距离
    private int mPhotoTop;  //图片距离上边的距离
    private int mPhotoNeedMoveDistanceX;  // 图片需要移动的X距离
    private int mPhotoNeedMoveDistanceY;  // 图片需要移动的Y距离
    //需要移动的文字
    private int mTextLeft;  //文字距左边的距离
    private int mTextTop;  //文字距离上边的距离
    private int mTextNeedMoveDistanceX;  // 文字需要移动的X距离
    private int mTextNeedMoveDistanceY;  //文字需要移动的Y距离
    //*********************************************

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        initView();
        initDistance();
    }

    private void initView() {
        listView= (ListView) findViewById(R.id.lv);
        rl_head= (RelativeLayout) findViewById(R.id.rl_head);
        iv_head= (ImageView) findViewById(R.id.iv_head);
        tv_name= (TextView) findViewById(R.id.tv_name);
        tv_other= (TextView) findViewById(R.id.tv_other);

        String []strs={"北京","上海","天津","北京","上海","天津","北京","上海","天津","北京","上海","天津","北京","上海","天津","北京","上海","天津","北京","上海","天津"};
        List<String> data= Arrays.asList(strs);

        adapter=new MyAdapter(this,data);
        listView.setAdapter(adapter);
    }

    /**
     * 初始化需要滚动的距离
     */
    private void initDistance() {
        mOrignHight = rl_head.getLayoutParams().height;
        mMinHight =100;  //设置最小的高度为这么多
        mNeedDistance = mOrignHight - mMinHight;
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) iv_head.getLayoutParams();
        mPhotoOriginHeight = params.height;
        mPhotoOriginWidth = params.width;
        mPhotoLeft = params.leftMargin;
        mPhotoTop = params.topMargin;
        mPhotoNeedMoveDistanceX = getWindowManager().getDefaultDisplay().getWidth() / 2 - mPhotoLeft - mMinHight;
        mPhotoNeedMoveDistanceY = mPhotoTop - 20;
        /*******************移动的文字初始化***************************/
        RelativeLayout.LayoutParams textParams = (RelativeLayout.LayoutParams) tv_name.getLayoutParams();
        mTextLeft = textParams.leftMargin;
        mTextTop = textParams.topMargin;
        mTextNeedMoveDistanceX = getWindowManager().getDefaultDisplay().getWidth() / 2 - mTextLeft + 10;
        mTextNeedMoveDistanceY = mTextTop - 20;  //这里计算有点误差,正确的应该是剪去获取textview高度的一半
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastY = (int) ev.getY();
              //  LogUtils.d(TAG, "ACTION_MOVE==mCurrentDistance" + mCurrentDistance);
                return super.dispatchTouchEvent(ev); //传递事件 例如可以用来子view的点击事件等
            case MotionEvent.ACTION_MOVE:
                int y = (int) ev.getY();
                int dy = mLastY - y;
            //    LogUtils.d(TAG, "ACTION_MOVE==mCurrentDistance" + mCurrentDistance);
                if (mCurrentDistance >= mNeedDistance && dy > 0) {
                    return super.dispatchTouchEvent(ev);  //传递事件
                }
                if (mCurrentDistance <= 0 && dy < 0) {
                    return super.dispatchTouchEvent(ev); //把事件传递进去
                }
                //改变布局
                changeTheLayout(dy);
                mLastY = y;
                break;
            case MotionEvent.ACTION_UP:
                checkTheHeight();
         //       LogUtils.d(TAG, "ACTION_MOVE==mCurrentDistance" + mCurrentDistance);
                return super.dispatchTouchEvent(ev);
        }

        return false;
    }


    /**
     * 通过滑动的偏移量
     *
     * @param dy
     */
    private void changeTheLayout(int dy) {
        final ViewGroup.LayoutParams layoutParams = rl_head.getLayoutParams();
        layoutParams.height = layoutParams.height - dy;
        rl_head.setLayoutParams(layoutParams);
        checkTheHeight();
        rl_head.requestLayout();
        //计算当前移动了多少距离
        mCurrentDistance = mOrignHight - rl_head.getLayoutParams().height;
        mRate = (float) (mCurrentDistance * 1.0 / mNeedDistance);
        changeTheAlphaAndPostion(mRate);  //获取偏移率然后改变某些控件的透明度,和位置
    }


    /**
     * 根据变化率来改变这些这些控件的变化率位置
     *
     * @param rate
     */
    private void changeTheAlphaAndPostion(float rate) {
        //先改变一些控件的透明度
        if (rate >= 1) {
            tv_other.setVisibility(View.GONE);
        } else {
            tv_other.setVisibility(View.VISIBLE);
            tv_other.setAlpha(1 - rate);
            tv_other.setScaleY(1 - rate);
            tv_other.setScaleX(1 - rate);
        }
        //接下来是改变控件的大小和位置了  (这就是关键了)
        RelativeLayout.LayoutParams photoParams = (RelativeLayout.LayoutParams) iv_head.getLayoutParams();
      //  photoParams.width = (int) (mPhotoOriginWidth - (rate * (mPhotoOriginWidth - mMinHight - 10)));
     //   photoParams.height = (int) (mPhotoOriginWidth - (rate * (mPhotoOriginWidth - mMinHight - 10)));
        photoParams.leftMargin = (int) (mPhotoLeft + mPhotoNeedMoveDistanceX * rate);
        photoParams.topMargin = (int) (mPhotoTop - mPhotoNeedMoveDistanceY * rate);
        iv_head.setLayoutParams(photoParams);
        //针对文字
        RelativeLayout.LayoutParams textParams = (RelativeLayout.LayoutParams) tv_name.getLayoutParams();
        textParams.leftMargin = (int) (mTextLeft + mTextNeedMoveDistanceX * rate);
        textParams.topMargin = (int) (mTextTop - mTextNeedMoveDistanceY * rate);
        tv_name.setLayoutParams(textParams);
    }


    /**
     * 检查上边界和下边界
     */
    private void checkTheHeight() {
        final ViewGroup.LayoutParams layoutParams = rl_head.getLayoutParams();
        if (layoutParams.height < mMinHight) {
            layoutParams.height = mMinHight;
            rl_head.setLayoutParams(layoutParams);
            rl_head.requestLayout();
        }
        if (layoutParams.height > mOrignHight) {
            layoutParams.height = mOrignHight;
            rl_head.setLayoutParams(layoutParams);
            rl_head.requestLayout();
        }

    }


}

 

 

根据这个思路  即可实现网上大多数 上拉下拉,收缩放大视图的效果

 

Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现

标签:world   undle   自动   super   get   天津   pre   coding   tde   

原文地址:https://www.cnblogs.com/bimingcong/p/9029491.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!