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

从来好事天生俭,自古瓜儿苦后甜。这篇文章主要讲述Android自定义View之上拉下拉列表 头部元素跟随 缩放平移效果的实现相关的知识,希望能为你提供帮助。
  滑动ListView列表然后 listView上边的视图 跟随着上拉或者下拉的距离 自动放大或者缩小  视图里边元素自动平移的效果

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

文章图片

 
思路很简单
根据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= https://www.songbingjia.com/android/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
【Android自定义View之上拉下拉列表 头部元素跟随 缩放平移效果的实现】 

    推荐阅读