滑动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. MySQL Error--打开过多文件导致数据库无法连接

    [此文抄自同事的邮件,当作笔记学习] 环境描述Mysql 5.5.21OS centos 5.8zabbix agent 2.4.3 情况描述现象数据库处于运行状态,但是无法创建新的连接,监控报警数据 ...

  2. Docker之 默认桥接网络与自定义桥接网卡

    docker引擎会默认创建一个docker0网桥,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和宿主机都放到同一个二层网络. 1. docker如何使用网桥 1.1 Linux虚拟网桥的特点 ...

  3. No input file specified.

    no input file specified 解决方法 2018年02月23日 14:25:07 tiramisuer8023 阅读数:36607   版权声明:本文为博主原创文章,未经博主允许不得 ...

  4. easyui layout布局的属性说明

    layout布局的属性说明: 名称 类型 描述 默认值 fit boolean 当设置为 true 时,就设置布局(layout)的尺寸适应它的父容器.当在 'body' 标签上创建布局(layout ...

  5. linux git pull/push时提示输入账号密码之免除设置

    1.先cd到根目录,执行git config --global credential.helper store命令 [root@iZ25mi9h7ayZ ~]# git config --global ...

  6. 前端-JavaScript1-1——JavaScript简介

    1.1 JavaScript用途 前端三层: 结构层   HTML           从语义的角度描述页面的结构 样式层   CSS               从审美的角度装饰页面 行为层   J ...

  7. 在Docker中监控Java应用程序的5个方法

    译者注:Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.通常情况下,监控的主要目的在于:减少宕机 ...

  8. go语言学习--处理map的无序输出

    最近工作中遇到了这样的一个场景,需要处理一个无限极分类的问题,对于数据结构的定义首先想到了,map,map[int]map[int]struct.通过两层map的定义归类parent_id和id的关系 ...

  9. 导出Excel(Ext 前台部分)

    开发思路: - 序列化当前GridPanel 数据, 表头结构(用于对应关系), 通过控制器Aspose写到Excel中, 然后返回临时文件地址, 弹出窗口下载. function btnExport ...

  10. cookie与session的区别是什么

    cookie与session的区别有:cookie以文本格式存储在浏览器上,存储量有限:而会话存储在服务端,可以无限量存储多个变量并且比cookie更安全 在php中可以指定站点的访问者信息存储在se ...