视差特效实现思路:
* 1.解析ontouch ACTION_Down ,Action_move ,ACTION_up 业务逻辑过于复杂
* 2,重写Listview的overScrollby方法.继承式自定义控件 根据用户下拉的距离,动态修改Headerview的高度
* a:拷贝文本资源到项目中,自定义控件继承ListView
* b:使用自定义控件,并往头部添加布局,设置适配器
* c:使用试图时,把ImageView传给我们的自定义控件
MainActivity里面的东西
public class
MainActivity
extends
AppCompatActivity {
private
ParallaListView
plv
;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.
activity_main
);
//a,view
plv
= (ParallaListView) findViewById(R.id.
plv
);
//B.ListView添加一个头布局 listview的上拉加载下拉刷新
View headview = View.
inflate
(
this
, R.layout.
layout_head
,
null
);
plv
.addHeaderView(headview);
final
ImageView iv_header = (ImageView) headview.findViewById(R.id.
iv_header
);
//等view界面全部绘制完毕的时候,去得到已经绘制的宽和高,查下这个方法,并做下笔记
iv_header.getViewTreeObserver().addOnGlobalLayoutListener(
new
ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void
onGlobalLayout() {
//宽和高已经测量完毕
plv
.setIv_header(
iv_header
);
}
});
//b.使用ListView的arrayadapter 添加文本的item
plv
.setAdapter(
new
ArrayAdapter(
this
, android.R.layout.
simple_list_item_1
, Cheeses.
NAMES
));
}
}
继承式控件
* 1.继承ListView 覆写构造方法
* 2.覆写overScrollby方法重点关注deltaY ,isTouchEvent方法
* 3.暴露一个方法,去得到外界的ImageView ,并测量ImageView控件的高度
* 4.覆写OnTouchEvent方法
第二个类
public class
ParallaListView
extends
ListView {
private
ImageView
iv_header
;
private int
drawableHeight
;
private int
orignalHeight
;
public
ParallaListView(Context context) {
this
(context,
null
);
}
public
ParallaListView(Context context, AttributeSet attrs) {
this
(context, attrs,
0
);
}
public
ParallaListView(Context context, AttributeSet attrs,
int
defStyleAttr) {
super
(context, attrs, defStyleAttr);
}
public void
setIv_header(ImageView iv_header) {
this
.
iv_header
= iv_header;
//b.获取图片的原始高度
drawableHeight
= iv_header.getDrawable().getIntrinsicHeight();
//c.获取ImageView控件的原始高度,以便回弹时,回弹到原始高度
orignalHeight
= iv_header.getHeight();
}
/*
A.滑动到listview两端时,才会被调用
/*
*deltay :竖直方向滑动的瞬间变化量,顶部下拉为-;顶部上拉为+;
* isTouchEvent是否是用户触摸拉动,true表示用户手指拉动,false是惯性
*
*
*/
@Override
protected boolean
overScrollBy(
int
deltaX,
int
deltaY,
int
scrollX,
int
scrollY,
int
scrollRangeX,
int
scrollRangeY,
int
maxOverScrollX,
int
maxOverScrollY,
boolean
isTouchEvent) {
//A.通过Log来验证参数的作用
System.
out
.println(
"deltaX--"
+ deltaX +
"deltaY--"
+ deltaY +
"scrollX--"
+ scrollX +
"scrollY--"
+ scrollY +
"scrollRangeX--"
+ scrollRangeX +
"scrollRangeY--"
+ scrollRangeY +
"maxOverScrollX--"
+ maxOverScrollX +
"maxOverScrollY--"
+ maxOverScrollY +
"isTouchEvent--"
+ isTouchEvent);
//a.顶部下拉,用户触摸的操作才执行视察效果("&"和"&&"和"|"和"||"区别)
if
(deltaY <
0
&& isTouchEvent) {
//a.deltaY是负值,我们要改为绝对值,累计给我们的iv_header高度
int
newHeight =
iv_header
.getHeight() + Math.
abs
(deltaY);
//b.避免图片的无限放大,是图片最大不能超过图片的本身的高度
if
(newHeight <=
drawableHeight
) {
//把新的高度值负值给控件,改变控件的高度
iv_header
.getLayoutParams().
height
= newHeight;
iv_header
.requestLayout();
}
}
return super
.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}
//c.覆写触摸事件,让滑动图片重新恢复原有的样子
//触摸事件的监听
@Override
public boolean
onTouchEvent(MotionEvent event) {
switch
(event.getAction()) {
case
MotionEvent.
ACTION_UP
:
//松开时,回调
//把当前的头布局的高度恢复初始高度
int
currentHeight =
iv_header
.getHeight();
//属性动画,改变高度的值,把我们当前头布局的高度,改为原始的高度
final
ValueAnimator animator = ValueAnimator.
ofInt
(currentHeight,
orignalHeight
);
//动画更新的监听
animator.addUpdateListener(
new
ValueAnimator.AnimatorUpdateListener() {
@Override
public void
onAnimationUpdate(ValueAnimator valueAnimator) {
//获取中间的值,并赋予控件新高度,可以使控件平稳回弹的效果
Integer animatedValue = (Integer)
animator
.getAnimatedValue();
System.
out
.println(
"fraction"
+
fraction
+
"animatedValue"
+ animatedValue);
//让新的高度生效
iv_header
.getLayoutParams().
height
= animatedValue;
iv_header
.requestLayout();
}
});
//动画的回弹效果,值越大,回弹越厉害
animator.setInterpolator(
new
OvershootInterpolator(
2
));
//设置动画的执行时间,单位值毫秒
animator.setDuration(
500
);
//动画执行
animator.start();
break
;
}
return super
.onTouchEvent(event);
}
}
第三个类
public class
Cheeses {
public static final
String[]
NAMES
=
new
String[]{
"宋江"
,
"卢俊义"
,
"吴用"
,
"公孙胜"
,
"关胜"
,
"林冲"
,
"秦明"
,
"呼延灼"
,
"花荣"
,
"柴进"
,
"李应"
,
"朱仝"
,
"鲁智深"
,
"武松"
,
"董平"
,
"张清"
,
"杨志"
,
"徐宁"
,
"索超"
,
"戴宗"
,
"刘唐"
,
"李逵"
,
"史进"
,
"穆弘"
,
"雷横"
,
"李俊"
,
"阮小二"
,
"张横"
,
"阮小五"
,
" 张顺"
,
"阮小七"
,
"杨雄"
,
"石秀"
,
"解珍"
,
" 解宝"
,
"燕青"
,
"朱武"
,
"黄信"
,
"孙立"
,
"宣赞"
,
"郝思文"
,
"韩滔"
,
"彭玘"
,
"单廷珪"
,
"魏定国"
,
"萧让"
,
"裴宣"
,
"欧鹏"
,
"邓飞"
,
" 燕顺"
,
"杨林"
,
"凌振"
,
"蒋敬"
,
"吕方"
,
"郭 盛"
,
"安道全"
,
"皇甫端"
,
"王英"
,
"扈三娘"
,
"鲍旭"
,
"樊瑞"
,
"孔明"
,
"孔亮"
,
"项充"
,
"李衮"
,
"金大坚"
,
"马麟"
,
"童威"
,
"童猛"
,
"孟康"
,
"侯健"
,
"陈达"
,
"杨春"
,
"郑天寿"
,
"陶宗旺"
,
"宋清"
,
"乐和"
,
"龚旺"
,
"丁得孙"
,
"穆春"
,
"曹正"
,
"宋万"
,
"杜迁"
,
"薛永"
,
"施恩"
,
"周通"
,
"李忠"
,
"杜兴"
,
"汤隆"
,
"邹渊"
,
"邹润"
,
"朱富"
,
"朱贵"
,
"蔡福"
,
"蔡庆"
,
"李立"
,
"李云"
,
"焦挺"
,
"石勇"
,
"孙新"
,
"顾大嫂"
,
"张青"
,
"孙二娘"
,
" 王定六"
,
"郁保四"
,
"白胜"
,
"时迁"
,
"段景柱"
,
"易宸锋"
};
}
一共三个item布局
第一个布局
activity_main
xml version=
"1.0"
encoding=
"utf-8"
?>
<
RelativeLayout
xmlns:
android
=
"http://schemas.android.com/apk/res/android"
android
:layout_width=
"match_parent"
android
:layout_height=
"match_parent"
>
<
com.zhangshixin.bwie.test0816.ParallaListView
android
:id=
"@+id/plv"
android
:layout_width=
"match_parent"
android
:
layout_height
=
"match_parent"
/>
RelativeLayout
>
第二个布局
layout_header
xml version=
"1.0"
encoding=
"utf-8"
?>
<
LinearLayout
xmlns:
android
=
"http://schemas.android.com/apk/res/android"
android
:orientation=
"vertical"
android
:layout_width=
"match_parent"
android
:layout_height=
"match_parent"
>
<
ImageView
android
:id=
"@+id/iv_header"
android
:layout_width=
"match_parent"
android
:layout_height=
"160dp"
android
:src=
"@drawable/parallax_img"
android
:scaleType=
"centerCrop"
/>
LinearLayout
>
第三个布局
simple_list_item_1
xml version=
"1.0"
encoding=
"utf-8"
?>
<
LinearLayout
xmlns:
android
=
"http://schemas.android.com/apk/res/android"
android
:orientation=
"vertical"
android
:layout_width=
"match_parent"
android
:layout_height=
"match_parent"
>
LinearLayout
>