您的位置:首页 > 其它

自定义View实现视差特效

2017-08-17 09:53 197 查看
今天我来为大家阐述一下视差特效,及回弹操作:

* 视差特效实现思路:
* 1.解析OnTouche,Action_Down,Action_move,Action_up
* 2.重写listview的ouverScrollyBy方法,继承式自定义控件ListView,根据用户下拉的距离,动态修改headerView的高度.
*   a.拷贝文本资源到项目中,自定义控件继承Listview
*   b.使用自定义控件,并往头部添加布局,设置适配器.
*   c.使用视图树,把ImageView传给我们的自定义控件
*
*   实现思路以及代码里的注释我已经标记的很详细了,直接照代码撸就能实现效果
*

首先 :我们来撸 MainActivity 里的代码:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// A.View
final ParallaxListView plv = (ParallaxListView) findViewById(R.id.piv);

// B.ListView添加一个头布局
View headerView = View.inflate(this, R.layout.header, null);
plv.addHeaderView(headerView);

final ImageView iv_header = (ImageView) headerView.findViewById(R.id.iv_header);

// 待View界面全部绘制完毕的时候,去得到已经绘制完控件的宽和高,
iv_header.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 宽 和 高 已经测量完毕
plv.setPrallaxImage(iv_header);
// 释放资源
iv_header.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});

// B.使用ListView的ArrayAdapter,添加文本的Item
plv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, Cheeses.NAMES));
}
}


给Util工具类,同样借用梁山好汉109将


public class Cheeses {

public static final String[] NAMES = new String[]{"宋江", "卢俊义", "吴用",
"公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
"武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
"雷横", "李俊", "阮小二", "张横", "阮小五", "张顺", "阮小七", "杨雄", "石秀", "解珍",
"解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
"魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
"郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
"李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
"陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
"周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
"李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", "王定六", "郁保四", "白胜",
"时迁", "段景柱", "高会全"};

}
自定义View :


/**
*
* author:(Administrator)
* function: 继承式控件
* 1.继承listview,覆写构造方法.
* 2.覆写ouverScrollyBy方法,重点的两个方法(deltaY,isTouchEvent)
* 3.暴露一个方法,去得到外界的ImageView,并测量ImageView控件的高度.
* 4.覆写OnTouchEvent方法
*/

public class ParallaxListView extends ListView {

private ImageView iv_header;
private int Drawable;
private int orignlHeight;

public ParallaxListView(Context context) {
this(context, null);
}

public ParallaxListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public void setPrallaxImage(ImageView iv_header) {

this.iv_header = iv_header;
// B.获取图片的原始高度
Drawable = iv_header.getDrawable().getIntrinsicHeight();
// C.获取ImageView控件的原始高度,以便回弹时,回弹到原始高度
orignlHeight = iv_header.getHeight();
}

/**
* A. 滑动到ListView两端的时候才被调用
* @param deltaY 竖直方向滑动的瞬时变化量,顶部下拉为 - ; 顶部上拉为 + ;
* @param scrollY
* @param scrollRangeY
* @param maxOverScrollY
* @param isTouchEvent 是否是用户触摸拉动,true表示用户手指拉动,false是惯性
* @return
*/
@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("deltaY"+deltaY);
System.out.println("scrollY"+scrollY);
System.out.println("scrollRangeY"+scrollRangeY);
System.out.println("maxOverScrollY"+maxOverScrollY);
System.out.println("isTouchEvent"+isTouchEvent);
// A. 顶部下拉,用户触摸的操作才执行视差效果
if(deltaY < 0 && isTouchEvent){
// A.deltaY 是负值,我们要改为绝对值,累计给我们的 iv_header 高度
int newHeight = iv_header.getHeight() + Math.abs(deltaY);

/**
*
* 避免图片的无限放大,使图片最大不能超过图片本身的高度
*
*/

//B.避免图片的无限放大,是图片最大不能够超过图片本身的高度
if(newHeight <= Drawable){
//把新的高度值负值给控件,改变控件的高度
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 ev) {

switch (ev.getAction()){
case MotionEvent.ACTION_UP: // 松开时回调
// 把当前的头布局的高度恢复到原始的高度
int currentHeight = iv_header.getHeight();

// 属性动画,改变高度的值,把我们当前头布局的高度,改为原始高度
final ValueAnimator animator = ValueAnimator.ofInt(currentHeight, orignlHeight);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {

// 获取动画执行过程中的分度值
float fraction = animator.getAnimatedFraction();

// 获取中间的值,并赋给控件新高度,可以使控件平稳回弹的效果;
Integer value = (Integer) animator.getAnimatedValue();

// 让新的高度生效
iv_header.getLayoutParams().height = value;
iv_header.requestLayout();
}
});

// 设置动画执行时间
animator.setDuration(3000);

// 动画执行
animator.start();

}
return super.onTouchEvent(ev);
}
}
XML _ activity_main 中:

<?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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.demo.MainActivity">

<com.example.administrator.demo.ParallaxListView
android:id="@+id/piv"
android:layout_width="match_parent"
android:layout_height="match_parent"></com.example.administrator.demo.ParallaxListView>
</RelativeLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  自定义View