版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】Android中怎么利用ListView实现下拉顶部图片变大效果
Android中怎么利用ListView实现下拉顶部图片变大效果,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。变量说明这里变量包含了:自定义返回动画加速度、自定义动画线程、头部图片view,最后的y坐标,做好的比例,做大的比例等。private
static
final
String
TAG
=
"PullToZoomListView";
private
static
final
int
INVALID_VALUE
=
-1;//重置值
//自定义加速度动画
private
static
final
Interpolator
sInterpolator
=
new
Interpolator()
{
public
float
getInterpolation(float
interpolator)
{
float
f
=
interpolator
-
1.0F;
return
1.0F
+
f
*
(f
*
(f
*
(f
*
f)));
}
};
private
int
mActivePointerId
=
INVALID_VALUE;//当前手指的Id
private
FrameLayout
mHeaderContainer;//头部
private
int
mHeaderHeight;//头部图片的高度
private
ImageView
mHeaderImage;//头部图片
float
mLastMotionY
=
INVALID_VALUE;//最后y坐标
float
mLastScale
=
INVALID_VALUE;//最后的比例
float
mMaxScale
=
INVALID_VALUE;//最大的比例
private
OnScrollListener
mOnScrollListener;//滑动监听
private
ScalingRunnalable
mScalingRunnalable;//动画线程
private
int
mScreenHeight;//屏幕高度
private
ImageView
mShadow;//阴影遮罩自定义View初始化:设置了头部的头部和遮罩并且设置了监听。/**
*
初始化
*
@param
paramContext
*/
private
void
init(Context
paramContext)
{
DisplayMetrics
metrics
=
new
DisplayMetrics();
((Activity)
paramContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
this.mScreenHeight
=
metrics.heightPixels;//屏幕高度赋值
this.mHeaderContainer
=
new
FrameLayout(paramContext);//头部
this.mHeaderImage
=
new
ImageView(paramContext);//头部图片
int
screenWidth
=
metrics.widthPixels;//屏幕宽度
//设置头部View的样式
设置屏幕宽度,最大样式高度为屏幕高度的9/16
setHeaderViewSize(screenWidth,
(int)
(9.0F
*
(screenWidth
/
16.0F)));
this.mShadow
=
new
ImageView(paramContext);//遮罩
FrameLayout.LayoutParams
layoutParams
=
new
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
layoutParams.gravity
=
Gravity.CENTER;
this.mShadow.setLayoutParams(layoutParams);//设置遮罩样式
//头部添加View
this.mHeaderContainer.addView(this.mHeaderImage);
this.mHeaderContainer.addView(this.mShadow);
//添加头部
addHeaderView(this.mHeaderContainer);
//初始化返回动画
this.mScalingRunnalable
=
new
ScalingRunnalable();
//设置监听
super.setOnScrollListener(this);
}开启动画:判断当前的头部布局底部的位置–是否大于图片的初始化高度。/**
*
开启动画
*/
private
void
endScraling()
{
if
(this.mHeaderContainer.getBottom()
>=
this.mHeaderHeight)
{
Log.d(TAG,
"this.mScalingRunnalable.startAnimation(200L)");
this.mScalingRunnalable.startAnimation(200L);
}
}多指触碰时将第0个手指赋值。/**
*
多点触碰的时候按下,当第0个有手指抬起,再次有手指按下后,将按下的事件的手指指针作为当前手指指针
*
*
@param
motionEvent
*/
private
void
onSecondaryPointerUp(MotionEvent
motionEvent)
{
Log.d(TAG,
"onSecondaryPointerUp
motionEvent.getPointerId(0)
=
"
+
motionEvent.getPointerId(0));
Log.d(TAG,
"onSecondaryPointerUp
this.mActivePointerId
=
"
+
this.mActivePointerId);
if
(motionEvent.getPointerId(0)
==
this.mActivePointerId)
{
this.mLastMotionY
=
motionEvent.getY(0);
this.mActivePointerId
=
motionEvent.getPointerId(0);
}
Log.d(TAG,
"onSecondaryPointerUp
mLastMotionY
=
"
+
mLastMotionY);
Log.d(TAG,
"onSecondaryPointerUp
mActivePointerId
=
"
+
mActivePointerId);
}重置所有的数据/**
*
重置所有数据
*/
private
void
reset()
{
this.mActivePointerId
=
INVALID_VALUE;
this.mLastMotionY
=
INVALID_VALUE;
this.mMaxScale
=
INVALID_VALUE;
this.mLastScale
=
INVALID_VALUE;
}向上滚动时修改布局样式@Override
public
void
onScroll(AbsListView
view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount)
{
Log.d(TAG,
"onScroll");
float
bottomSpacing
=
this.mHeaderHeight
-
this.mHeaderContainer.getBottom();
Log.d(TAG,
"onScroll
bottomSpacing
=
"
+
bottomSpacing);
if
((bottomSpacing
>
0.0F)
&&
(bottomSpacing
<
this.mHeaderHeight))
{//如果是向上滑动
int
toUpScroll
=
(int)
(0.65D
*
bottomSpacing);
this.mHeaderImage.scrollTo(0,
-toUpScroll);
Log.d(TAG,
"onScroll
向上滑动
toUpScroll
=
"
+
toUpScroll);
}
else
if
(this.mHeaderImage.getScrollY()
!=
0)
{
Log.d(TAG,
"onScroll
this.mHeaderImage.getScrollY()
=
"
+
this.mHeaderImage.getScrollY());
this.mHeaderImage.scrollTo(0,
0);
}
if
(this.mOnScrollListener
!=
null)
{
this.mOnScrollListener.onScroll(view,
firstVisibleItem,
visibleItemCount,
totalItemCount);
}
}不同事件处理,修改布局样式@Override
public
boolean
onTouchEvent(MotionEvent
motionEvent)
{
switch
(motionEvent.getAction()
&
MotionEvent.ACTION_MASK)
{
case
MotionEvent.ACTION_OUTSIDE:
case
MotionEvent.ACTION_DOWN:
if
(!this.mScalingRunnalable.mIsFinished)
{
this.mScalingRunnalable.abortAnimation();
}
this.mLastMotionY
=
motionEvent.getY();
//获取第一个手指指针的ID
this.mActivePointerId
=
motionEvent.getPointerId(0);
this.mMaxScale
=
(this.mScreenHeight
/
this.mHeaderHeight);
this.mLastScale
=
(this.mHeaderContainer.getBottom()
/
this.mHeaderHeight);
Log.d(TAG,
"onTouchEvent
ACTION_DOWN
mLastMotionY
=
"
+
mLastMotionY);
Log.d(TAG,
"onTouchEvent
ACTION_DOWN
mActivePointerId
=
"
+
mActivePointerId);
Log.d(TAG,
"onTouchEvent
ACTION_DOWN
mMaxScale
=
"
+
mMaxScale);
Log.d(TAG,
"onTouchEvent
ACTION_DOWN
mLastScale
=
"
+
mLastScale);
break;
case
MotionEvent.ACTION_MOVE:
Log.d(TAG,
"onTouchEvent
ACTION_MOVE
mActivePointerId"
+
mActivePointerId);
//获取当前id的手机指针
int
pointer
=
motionEvent.findPointerIndex(this.mActivePointerId);
//判断指针不为空
if
(pointer
==
INVALID_VALUE)
{
Log.e(TAG,
"Invalid
pointerId="
+
this.mActivePointerId
+
"
in
onTouchEvent");
}
else
{
//如果开始没有赋值,则需要赋值
if
(this.mLastMotionY
==
INVALID_VALUE)
{
this.mLastMotionY
=
motionEvent.getY(pointer);
}
if
(this.mHeaderContainer.getBottom()
>=
this.mHeaderHeight)
{
//获取头部样式
ViewGroup.LayoutParams
headerParams
=
this.mHeaderContainer.getLayoutParams();
float
currentScale
=
((motionEvent.getY(pointer)
-
this.mLastMotionY
+
this.mHeaderContainer.getBottom())
/
this.mHeaderHeight
-
this.mLastScale)
/
2.0F
+
this.mLastScale;
if
((this.mLastScale
<=
1.0D)
&&
(currentScale
<
this.mLastScale))
{
//最后比例小于默认并且当前的比例要小于上次的比例,则修改头部的高度
headerParams.height
=
this.mHeaderHeight;
this.mHeaderContainer.setLayoutParams(headerParams);
return
super.onTouchEvent(motionEvent);
}
else
{
//否则,将当前的比例赋值为最后一次的比例
this.mLastScale
=
Math.min(Math.max(currentScale,
1.0F),
this.mMaxScale);
headerParams.height
=
((int)
(this.mHeaderHeight
*
this.mLastScale));
//判断修改后的高度小于屏幕的高度
if
(headerParams.height
<
this.mScreenHeight)
{
this.mHeaderContainer.setLayoutParams(headerParams);
}
//记录最后的y坐标
this.mLastMotionY
=
motionEvent.getY(pointer);
return
true;
}
}
this.mLastMotionY
=
motionEvent.getY(pointer);
}
break;
case
MotionEvent.ACTION_UP:
Log.d(TAG,
"onTouchEvent
ACTION_UP
重置");
//重置
reset();
//当手指起来的时候,结算拉伸,判断是否开启动画
endScraling();
break;
case
MotionEvent.ACTION_CANCEL:
int
actionIndex
=
motionEvent.getActionIndex();//获取当前最上层的指针
this.mLastMotionY
=
motionEvent.getY(actionIndex);//获取最后的y坐标
this.mActivePointerId
=
motionEvent.getPointerId(actionIndex);//获取最上层指针的手指
Log.d(TAG,
"onTouchEvent
ACTION_CANCEL
actionIndex
=
"
+
actionIndex
+
"
mLastMotionY
=
"
+
mLastMotionY
+
"
mActivePointerId
=
"
+
mActivePointerId);
break;
case
MotionEvent.ACTION_POINTER_DOWN:
//当第二个手指按下或者放开触发这个事件
onSecondaryPointerUp(motionEvent);
this.mLastMotionY
=
motionEvent.getY(motionEvent.findPointerIndex(this.mActivePointerId));
Log.d(TAG,
"onTouchEvent_Po
ACTION_POINTER_DOWN
mLastMotionY
=
"
+
mLastMotionY);
break;
case
MotionEvent.ACTION_POINTER_UP:
//当第二个手指按下或者放开
Log.d(TAG,
"onTouchEvent_Po
ACTION_POINTER_UP
");
break;
}
return
super.onTouchEvent(motionEvent);
}向上返回时的动画/**
*
向上返回的动画
*/
class
ScalingRunnalable
implements
Runnable
{
long
mDuration;//持续时间
boolean
mIsFinished
=
true;//是否结束
float
mScale;//比例
long
mStartTime;//开始时间
ScalingRunnalable()
{
}
/**
*
中止动画
*/
public
void
abortAnimation()
{
this.mIsFinished
=
true;
}
/**
*
是否中止
*
*
@return
*/
public
boolean
isFinished()
{
return
this.mIsFinished;
}
public
void
run()
{
Log.d(TAG,
"ScalingRunnalable
mIsFinished
=
"
+
this.mIsFinished
+
"
this.mScale
=
"
+
this.mScale);
float
currentScale;
ViewGroup.LayoutParams
mHeaderContainerParams;//头部样式
//判断是否中止和已经滑动超过的默认大小
if
((!this.mIsFinished)
&&
(this.mScale
>
1.0D))
{
float
currentTime
=
((float)
SystemClock.currentThreadTimeMillis()
-
(float)
this.mStartTime)
/
(float)
this.mDuration;
currentScale
=
this.mScale
-
(this.mScale
-
1.0F)
*
PullToZoomListView.sInterpolator.getInterpolation(currentTime);
Log.d(TAG,
"ScalingRunnalable
currentTime
=
"
+
currentTime
+
"
currentScale
=
"
+
currentScale);
mHeaderContainerParams
=
PullToZoomListView.this.mHeaderContainer.getLayoutParams();
if
(currentScale
>
1.0F)
{
Log.d(TAG,
"ScalingRunnalable
currentScale
>
1.0
--
修改头部高度");
mHeaderContainerParams.height
=
PullToZoomListView.this.mHeaderHeight;
mHeaderContai
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024医疗赔偿协议书范本
- 2024业务保密协议书范例
- 2024包装商品购销合同
- 2024保密部门的保密协议书大全
- 2024个人委托合同模板
- 2024全新增资扩股入股协议下载
- 材料范文之女职工经验交流材料
- 材料物理性能复习总结
- 关于《唐山大地震》观后感500字5篇
- 一年级下册音乐教案 第三单元 唱歌 谁唱歌|人教版
- 做一个幸福的教师读书体会
- 开发建设项目水土保持设施验收技术规程.ppt
- Mr-Imagination
- 高中三年成绩单模板
- 《目标管理》PPT课件
- 汽车与设计课程设计
- 弱电考试题库(含答案)
- 人教版小学二年级下册数学应用题练习 共8套
- 蓝色星星年会邀请函word模板.doc
- 举升机维护保养记录表
- 垃圾站施工组织设计(完整版)
评论
0/150
提交评论