zoukankan      html  css  js  c++  java
  • Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现

      滑动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();
            }
    
        }
    
    
    }

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

    严禁盗版    

    转载请注明出处:https://www.cnblogs.com/bimingcong/p/9029491.html

  • 相关阅读:
    centos ssh远程登陆
    Vim 技巧
    php and js to facebook登陆 最佳实践
    vim 编辑器常规操作
    js 函数定义三种方式
    ORDER BY 默认升序排列
    sql = 和<>遵循的sql-92标准的设置SET ANSI_NULLS ON
    添加FB登陆时,需要curl扩展
    array(1) { [0]=> int(5) }和array(1) { [0]=> string(1) "5" }
    Android第三方推送引擎比较
  • 原文地址:https://www.cnblogs.com/bimingcong/p/9029491.html
Copyright © 2011-2022 走看看