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
Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现的更多相关文章
- Android自定义View(LimitScrollerView-仿天猫广告栏上下滚动效果)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53303872 本文出自:[openXu的博客] 1分析 2定义组合控件布局 3继承最外层控件 ...
- (转)[原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- Android 自定义 view(四)—— onMeasure 方法理解
前言: 前面我们已经学过<Android 自定义 view(三)-- onDraw 方法理解>,那么接下我们还需要继续去理解自定义view里面的onMeasure 方法 推荐文章: htt ...
- Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程
转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...
- Android 自定义View及其在布局文件中的使用示例(二)
转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...
- [原] Android 自定义View步骤
例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
- [原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android自定义View
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...
随机推荐
- 2017第45周一java多线程创建方法
1. 从JDK1.5开始,Java提供了3种方式来创建,启动多线程: Ø 继承Thread类来创建线程类,重写run()方法作为线程执行体. Ø 实现Runnable接口来创建线程类,重写run()方 ...
- Vue 中使用 viewerjs
安装 viewerjs npm install viewerjs --save 创建一个 Viewer.vue 组件 <template> <div id="index&q ...
- Transaction rolled back because it has been marked as rollback-only 原因 和解决方案
产生原因 , 1 serviceA 调用 serviceB 然后 B 抛出异常 ,B 所在的 事物 回滚,B 把当前可写 事物标记成 只读事物 , 2 如果 A 和B 是在 同一个事物环境,并且 ...
- Spark Streaming 'numRecords must not be negative'问题解决
转载自:http://blog.csdn.net/xueba207/article/details/51135423 问题描述 笔者使用spark streaming读取Kakfa中的数据,做进一步处 ...
- 依赖、耦合、解耦、控制反转(IOC)、依赖注入(DI)
随着net的深入学习,出现了很多概念性的东西需要理解,现在统一记录一下. 1.依赖:现阶段在任何一个有请求作用的系统,都会出现A类调用B类的情况,这时候A类就依赖于B类,A类和B类存在依赖关系. 2. ...
- DotNetBar中Supergrid显示树形数据
1.向窗体中拖一个Supergrid控件 2.添加列ID,NAME,MATH,CN,SEX 3.在任务窗格中勾选“Show Tree Lines”和“Show Tree Buttons” 4.添加数据 ...
- Linux下的文件操作——基于文件指针的文件操作(缓冲)
目录操作 创建和删除目录: 原型为: #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> ...
- 黑色背景下 vs把{}括号变黑问题
最近喜欢把VS的背景搞成黑色,据说这样可以对眼睛好一点,然后就蛋疼的碰到点击括号中的内容,括号就变黑的问题,这样黑色背景下就什么看不到了. 原因是装了番茄助手导致的,解决办法,把选中行VA Brace ...
- WordPress版微信小程序2.1.5版发布
WordPress版微信小程序功能已经基本完善,利用这套程序,搭配WordPress提供的rest api,WordPress网站的站长可以快速搭建属于自己的网站微信小程序 . WordPress版微 ...
- day39数据库之基本数据类型
数据库之数据类型1.数据存储引擎 一个功能的核心部分,回到mysql 核心功能是存储数据 涉及到存储数据的代码 就称之为存储引擎 根据不同的需求 也有着不同的引擎分类 不 ...