最近有研究了QQ空間可拉伸頭部控制元件的listView。如何去做呢?這裡使用了自定義listView的方法。先看效果圖吧:
究竟如何去做呢?
可以用的方法有:
- 1.繼承 extends ViewGrop
- 2.RecycleView +Behavior+CoordinateLayout
- 3.ViewGroup 組合控制元件
- 4.ListView + headView
這次我們主要用原生的自定義listView去做。
- 1.extends 繼承 ListView
- 2.監聽過度監聽,在縮放頭部圖片重寫overScrollBy方法
- 重寫onScrollChanged方法監聽度放大時,執行縮小圖片
- 重寫onTouchEvent方法,執行觸控時釋放事件的處理
/** * 類功能描述:<
/br>
* 仿QQ空間之打造個性化可拉伸頭部控制元件<
/br>
* @author yuyahao * @version 1.0 <
/p>
修改時間:<
/br>
修改備註:<
/br>
*/public class CustomerScrollZoomListView extends ListView{
private ImageView imageView;
private int mMeasureWeight;
public CustomerScrollZoomListView(Context context, AttributeSet attrs) {
super(context, attrs);
mMeasureWeight = context.getResources().getDimensionPixelSize(R.dimen.dp200);
} public CustomerScrollZoomListView(Context context) {
super(context);
} public void setZoomImageView(ImageView iView ){
imageView = iView;
} @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
if(deltaY <
0){//下拉過度 對圖片進行放大 imageView.getLayoutParams().height = imageView.getHeight() - deltaY;
imageView.requestLayout();
}else{//上拉過度時 imageView.getLayoutParams().height = imageView.getHeight() - deltaY;
imageView.requestLayout();
} LogUtil.i("yuyahao","deltaY: "+deltaY);
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
} @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) {
//只有當imageView過度放大時,這裡才會去執行縮小 View view = (View) imageView.getParent();
int detalY = view.getTop();
//此時 detay 為負值 if(imageView.getHeight() >
mMeasureWeight){//如果當前圖片的高度 >
初始高度 imageView.getLayoutParams().height = imageView.getHeight() + detalY;
imageView.requestLayout();
} LogUtil.i("yuyahao","---- deltaY: "+detalY);
super.onScrollChanged(l, t, oldl, oldt);
} @Override public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_UP://鬆手釋放時 MyCustomserAnimation myCustomserAnimation = new MyCustomserAnimation(mMeasureWeight);
myCustomserAnimation.setDuration(300);
myCustomserAnimation.setInterpolator(new BounceInterpolator());
imageView.startAnimation(myCustomserAnimation);
break;
} return super.onTouchEvent(ev);
} public class MyCustomserAnimation extends Animation{
private int delay ;
//高度差 private int currentHeight ;
//當前的高度 public MyCustomserAnimation( int targetHeight){
//this.delay = delay;
delay = imageView.getHeight() - targetHeight;
currentHeight = imageView.getHeight();
} @Override protected void applyTransformation(float interpolatedTime, Transformation t) {
imageView.getLayoutParams().height = (int) (currentHeight - delay * interpolatedTime);
imageView.requestLayout();
super.applyTransformation(interpolatedTime, t);
}
}
}複製程式碼
這裡重寫了overScrollBy方法
這裡原始碼是怎麼說的呢?
/** * This is called in response to an internal scroll in this view (i.e., the * view scrolled its own contents). This is typically as a result of * {@link #scrollBy(int, int)
} or {@link #scrollTo(int, int)
} having been * called. * * @param l Current horizontal scroll origin. * @param t Current vertical scroll origin. * @param oldl Previous horizontal scroll origin. * @param oldt Previous vertical scroll origin. */ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
notifySubtreeAccessibilityStateChangedIfNeeded();
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
postSendViewScrolledAccessibilityEventCallback();
} mBackgroundSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
} final AttachInfo ai = mAttachInfo;
if (ai != null) {
ai.mViewScrollChanged = true;
} if (mListenerInfo != null &
&
mListenerInfo.mOnScrollChangeListener != null) {
mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
}
}複製程式碼
大致意思我們都可以看得出來.大致意思是響應於該檢視中的內部滾動而呼叫的(即檢視滾動其自己的內容)比如:eltaY <
0的時候下拉過度 對圖片進行放大。 小於0時,上拉過度。
日前google上搜尋“android overscroll”,對此效果的介紹很多,但關於其具體使用方式和實現,則很少涉及,偶有提及,也經常答非所問或似是而非,反而誤導了別人。於是我查閱了android相關原始碼,並做了一些測試,在此講講我的理解。
首先是overscroll功能本身。
- 在最頂層的View類提供了支援,可通過setOverScrollMode函式控制其出現條件。但其實View中並沒有實現overscroll功能,
- 提供了一個輔助函式overScrollBy,該函式根據overScrollMode和內容是否需要滾動控制最大滾動範圍。
- 最後將計算結果傳給onOverScrolled實現具體的overscroll功能
- 但此函式在View類中是全空的
overscroll功能真正的實現分別在ScrollView、AbsListView、HorizontalScrollView和WebView中各有一份,程式碼基本一樣。 - 以ScrollView為例,它在處理筆點移動訊息時呼叫overScrollBy來滾動檢視,然後過載了overScrollBy函式來實現具體功能,其位置計算通過OverScroller類實現。
- OverScroller作為一個計算引擎,應該是一個獨立的模組,具體滾動效果和範圍都不可能通過它來設定,我覺得沒有必要細看。但滾動位置最終是它給出的,那相關資料肯定要傳遞給它。
- 回頭看overScrollBy函式,它有兩個控制overScroll出界範圍的引數,幾個實現裡面都是取自ViewConfiguration.getScaledOverscrollDistance,而這個引數的值在我的原始碼中都是0,而且我沒找到任何可以影響其結果的設定。
Activity中的程式碼:
/** * 類功能描述:<
/br>
* 仿QQ空間之打造個性化可拉伸頭部控制元件<
/br>
* @author yuyahao * @version 1.0 <
/p>
修改時間:<
/br>
修改備註:<
/br>
*/public class CustomerScrollZoomListViewActivity extends BaseActivity{
@Bind(R.id.lv_customser_zoomscroll) CustomerScrollZoomListView lv_customser_zoomscroll;
private List<
Student>
list = new ArrayList<
>
();
private ZoomScrollListViewAdapter zoomScrollListViewAdapter;
private View headView;
@Override protected void initData() {
setContentView(R.layout.activity_customerscrollzoomlistview);
ButterKnife.bind(this);
list.addAll(ServiceData.getStudentList());
zoomScrollListViewAdapter = new ZoomScrollListViewAdapter(CustomerScrollZoomListViewActivity.this,list,R.layout.item_xzoomscrollview);
headView = LayoutInflater.from(CustomerScrollZoomListViewActivity.this).inflate(R.layout.zoom_headview,null);
ImageView iamgeView = (ImageView) headView.findViewById(R.id.iv_zoom_head);
lv_customser_zoomscroll.setZoomImageView(iamgeView);
lv_customser_zoomscroll.addHeaderView(headView);
lv_customser_zoomscroll.setAdapter(zoomScrollListViewAdapter);
}
}複製程式碼
xml佈局
<
?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">
<
com.yolo.myapplication.activity.view.CustomerScrollZoomListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv_customser_zoomscroll" />
<
/LinearLayout>
複製程式碼
adapter介面卡
public class ZoomScrollListViewAdapter extends CommonAdapter<
Student>
{
private Context context;
public ZoomScrollListViewAdapter(Context context, List<
Student>
listDatas, int layoutId) {
super(context, listDatas, layoutId);
this.context = context;
} @Override protected void fillData(ViewHolder holder, int position) {
TextView actNum = holder.getView(R.id.team_item_active_num);
TextView time = holder.getView(R.id.team_item_time);
TextView title = holder.getView(R.id.team_item_title);
ImageView icon = holder.getView(R.id.team_item_icon);
Student item = listDatas.get(position);
actNum.setText(String.valueOf(item.getList().size()) + "");
time.setText(String.valueOf(item.getList().get(0).getPerListenceName()) + "");
title.setText(item.getName());
}
}複製程式碼
adapter介面卡請參考:
教你打造一個萬能的介面卡
item:佈局
<
?xml version="1.0" encoding="utf-8"?>
<
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:gravity="center_vertical" android:layout_height="match_parent">
<
ImageView android:layout_width="@dimen/dp80" android:layout_height="@dimen/dp80" android:background="@drawable/img2" android:scaleType="fitXY" android:id="@+id/team_item_icon"/>
<
LinearLayout android:layout_width="match_parent" android:layout_marginLeft="@dimen/dp10" android:orientation="vertical" android:layout_height="@dimen/dp80">
<
TextView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/team_item_title" android:gravity="center_vertical" android:layout_weight="1" android:text="卡卡羅特"/>
<
LinearLayout android:layout_width="match_parent" android:layout_weight="1" android:layout_height="match_parent" android:gravity="center_vertical">
<
TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="天不排名" android:id="@+id/team_item_time"/>
<
TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp20" android:text="戰鬥值: " android:id="@+id/team_item_active_num"/>
<
/LinearLayout>
<
/LinearLayout>
<
/LinearLayout>
複製程式碼
專案原始碼地址:MyZoomListView.rar
如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部
(歡迎關注學習和交流)