滑动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

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

  1. Android自定义View(LimitScrollerView-仿天猫广告栏上下滚动效果)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53303872 本文出自:[openXu的博客] 1分析 2定义组合控件布局 3继承最外层控件 ...

  2. (转)[原] Android 自定义View 密码框 例子

    遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...

  3. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  4. Android 自定义 view(四)—— onMeasure 方法理解

    前言: 前面我们已经学过<Android 自定义 view(三)-- onDraw 方法理解>,那么接下我们还需要继续去理解自定义view里面的onMeasure 方法 推荐文章: htt ...

  5. Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...

  6. Android 自定义View及其在布局文件中的使用示例(二)

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...

  7. [原] Android 自定义View步骤

    例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...

  8. [原] Android 自定义View 密码框 例子

    遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...

  9. Android自定义View

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...

随机推荐

  1. 子数组的最大异或和---Trie

    异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法. 前缀树详解:https://www.cnblog ...

  2. linux安装redis标准流程-按这个来

    1.将下载好的压缩包放到/usr/local目录下# tar xzf redis-3.2.9.tar.gz # cd redis-3.2.9 # make 提示错误 make: cc: Command ...

  3. HBuilder后台保活开发(后台自动运行,定期记录定位数据)

    http://ask.dcloud.net.cn/question/28090 后台自动运行,定期记录定位数据 分类:HTML5+   各位新年好 小弟以前用hbuilder开发过几个项目,现在有一新 ...

  4. Flask--(一对多demo)作者书籍模型

    一对多模型的增加和删除 后端实现: from flask import Flask from flask import flash from flask import redirect from fl ...

  5. 【算法和数据结构】_15_小算法_打印EOF的值

    /* 本程序打印EOF的值 */ #include <stdio.h> int main(int argc,char* argv[],char* env) { printf("E ...

  6. Xamarin+Prism开发详解七:Plugin开发与打包测试

    有了上章[Xamarin+Prism开发详解六:DependencyService与IPlatformInitializer的关系]的基础,现在来理解Plugin开发就简单了. 本文实例代码地址:ht ...

  7. 【转载】robocopy的用法

    经常进行文件管理操作的朋友们,不满意于Windows系统内置的复制功能,因为它太龟速了.于是大家就使用FastCopy.TeraCopy之类的软件来加速复制,但是你是否知道Windows 7已经内置快 ...

  8. Docker镜像常用命令

    镜像(image)是Docker三大核心概念中最重要的,是运行容器的前提. Docker运行容器前需要本地存在对应的镜像,如果镜像没保存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Dock ...

  9. property用法

    用法一 class Test(object): def __init__(self): self.__Num = 100 def setNum(self,Num): print("---se ...

  10. note 2 运算符和表达式

    运算符 +.-.*./ %求余Modulus **指数Exponent 表达式 #C = 5/9 (F - 32) print 5.0/9*(75-32) 自动类型转换 类型相同,结果类型不变 1/2 ...