滑动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
时间: 2024-11-05 06:12:00