1. 程式人生 > >頭部視覺視差(仿QQ控制元件下拉效果)

頭部視覺視差(仿QQ控制元件下拉效果)

看到新版QQ空間出來的時候,首頁的下拉的效果比較炫酷,下拉的時候會把整張圖片顯示出來,鬆開手之後就會自己恢復原狀,不說了,上程式碼。

這是效果圖


public class ParallaxListView extends ListView {
//關於自定義控制元件
//onmeasure->onlayout->ondraw這是呼叫順序(也就是先測量,再擺放空間的位置,最後再把控制元件畫出來)
private int maxHeight;
private int orignalHeight;


public ParallaxListView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);
}


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


public ParallaxListView(Context context) {
super(context);
}
private ImageView imageView;
public void setParallaxImageView(final ImageView imageView){
this.imageView=imageView;

//設定最大高度
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {



@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
orignalHeight = imageView.getHeight();
int drawableHeight = imageView.getDrawable().getIntrinsicHeight();

maxHeight=orignalHeight>drawableHeight?orignalHeight*2:drawableHeight;//獲取圖片的高度
}
});

}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction()==MotionEvent.ACTION_UP) {
//恢復最初高度
ValueAnimator amAnimator=ValueAnimator.ofInt(imageView.getHeight(),orignalHeight);
amAnimator.addUpdateListener(new AnimatorUpdateListener() {

@Override
public void onAnimationUpdate(ValueAnimator animator) {
//獲取動畫的值,設定給imageview
int animatedValue = (int) animator.getAnimatedValue();
imageView.getLayoutParams().height=animatedValue;
imageView.requestLayout();//imageview的佈局引數生效
}
});
amAnimator.setInterpolator(new OvershootInterpolator());//彈性插補器
//這和插補器其實就是一個函式詳細可以參考這個網址http://www.2cto.com/kf/201306/222725.html
amAnimator.setDuration(350);
amAnimator.start();
}
return super.onTouchEvent(ev);
}
/**
* listview滑動到頭的時候執行,可以獲得listview 的滑動距離和方向
* deltaX:繼續滑動x方向的距離
* deltaY:繼續滑動y方向的距離
* maxOverScrollX:x方向最大滾動的距離
* isTouchEvent:是否 是手指拖動滑動true手指滑動 false:fling滑動,慣性滑動
*/
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
int scrollY, int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
if (imageView!=null) {
if (deltaY<0&&isTouchEvent) {
//表示頂部到頭,並且是手動到頭
//需要不斷增加imageview的高度
int newHeight=imageView.getHeight()-deltaY;
if (newHeight>maxHeight) {
newHeight=maxHeight;
}
imageView.getLayoutParams().height=newHeight;
imageView.requestLayout();//imageview的佈局引數生效
}
}

return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}

}

首先是佈局程式碼activity_main

<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"
     >


   <com.example.headerparallax.ParallaxListView
       android:id="@+id/listview"
       android:layout_width="match_parent"
    android:layout_height="match_parent"
       >
       
   </com.example.headerparallax.ParallaxListView>


</RelativeLayout>

佈局沒什麼好說的就是自定義了一個listview。



java程式碼MainActivity 

package com.example.headerparallax;


import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;


public class MainActivity extends Activity {


private ParallaxListView listView;
private String[] indexArr = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z" };
private ImageView imageView;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ParallaxListView) findViewById(R.id.listview);
listView.setOverScrollMode(ListView.OVER_SCROLL_NEVER);//永遠不顯示藍色陰影
// 新增header佈局
View headerView = View.inflate(this, R.layout.layout_header, null);
imageView = (ImageView) headerView.findViewById(R.id.imageview);
listView.setParallaxImageView(imageView);
listView.addHeaderView(headerView);
listView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, indexArr));

}
}

這個activity用的是一個ArrayAdapter,比較簡單,為了方便就沒有自定義介面卡。

接下來的就是重點了,

自定義的listview也就是ParallaxListView

public class ParallaxListView extends ListView {
//關於自定義控制元件
//onmeasure->onlayout->ondraw這是呼叫順序(也就是先測量,再擺放空間的位置,最後再把控制元件畫出來)
private int maxHeight;
private int orignalHeight;


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


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


public ParallaxListView(Context context) {
super(context);
}
private ImageView imageView;
public void setParallaxImageView(final ImageView imageView){
this.imageView=imageView;

//設定最大高度
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {



@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
orignalHeight = imageView.getHeight();
int drawableHeight = imageView.getDrawable().getIntrinsicHeight();

maxHeight=orignalHeight>drawableHeight?orignalHeight*2:drawableHeight;//獲取圖片的高度
}
});

}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction()==MotionEvent.ACTION_UP) {
//恢復最初高度
ValueAnimator amAnimator=ValueAnimator.ofInt(imageView.getHeight(),orignalHeight);
amAnimator.addUpdateListener(new AnimatorUpdateListener() {

@Override
public void onAnimationUpdate(ValueAnimator animator) {
//獲取動畫的值,設定給imageview
int animatedValue = (int) animator.getAnimatedValue();
imageView.getLayoutParams().height=animatedValue;
imageView.requestLayout();//imageview的佈局引數生效
}
});
amAnimator.setInterpolator(new OvershootInterpolator());//彈性插補器
//這和插補器其實就是一個函式詳細可以參考這個網址http://www.2cto.com/kf/201306/222725.html
amAnimator.setDuration(350);
amAnimator.start();
}
return super.onTouchEvent(ev);
}
/**
* listview滑動到頭的時候執行,可以獲得listview 的滑動距離和方向
* deltaX:繼續滑動x方向的距離
* deltaY:繼續滑動y方向的距離
* maxOverScrollX:x方向最大滾動的距離
* isTouchEvent:是否 是手指拖動滑動true手指滑動 false:fling滑動,慣性滑動
*/
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
int scrollY, int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
if (imageView!=null) {
if (deltaY<0&&isTouchEvent) {
//表示頂部到頭,並且是手動到頭
//需要不斷增加imageview的高度
int newHeight=imageView.getHeight()-deltaY;
if (newHeight>maxHeight) {
newHeight=maxHeight;
}
imageView.getLayoutParams().height=newHeight;
imageView.requestLayout();//imageview的佈局引數生效
}
}

return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}

}

最後,希望可以對你們有所幫助!

下載連結:http://download.csdn.net/detail/qq_32673327/9584545