国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

android仿QQ個人主頁下拉回彈效果

2019-12-12 03:34:04
字體:
供稿:網(wǎng)友

先看效果:

效果不錯吧!

進(jìn)入主題之前,先了解ImageView的scaleType的center_crop,網(wǎng)絡(luò)上說的已經(jīng)很清楚了 : 以下抄自網(wǎng)絡(luò):

1.Android:scaleType=”centerCrop”
以填滿整個ImageView為目的,將原圖的中心對準(zhǔn)ImageView的中心,等比例放大原圖,直到填滿ImageView為止(指的是ImageView的寬和高都要填滿),原圖超過ImageView的部分作裁剪處理。

均衡的縮放圖像(保持圖像原始比例),使圖片的兩個坐標(biāo)(寬、高)都大于等于 相應(yīng)的視圖坐標(biāo)(負(fù)的內(nèi)邊距)。圖像則位于視圖的中央。 在XML 中可以使用的語法:android:scaleType=”centerCrop”。

不說廢話,直接進(jìn)入主題!!

思路

1.先將topView的布局和listview平級,然后將topview以及topview包裹的imageView中傳listview,即一般是activity的layout
2.重寫listView的ontoucEvent()方法,但不做任何攔截,只在action時,控制imageView以及topView的高度,使其重新layout然后重新布局就可以了。
3.以上是大概思路,這里具體分析:當(dāng)action_down時記錄其初始位置,action_move時得到dy,通過dy來判斷是上啦還是下拉:
(1)dy>0,則是下拉,不斷重新設(shè)置topView和imageView的高度,又因為imageView的scaleType=center_crop,所以圖片會按照這個規(guī)則進(jìn)行等比拉伸,當(dāng)?shù)竭_(dá)圖片最大時就會有不斷放大的過程
當(dāng)松開手或者手指移出屏幕外時(action_up|action_outside|action_cancel)時讓其回到初始位置,并伴著回彈過程,這里通過自定義動畫讓其具備回彈效果
(2)dy<0,則是上拉,上推的過程,由于topView和Imageview不具備滾動的效果,所以上推也是通過控制topView和ImageView的高度,并且當(dāng)TopVIew和ImageView滑出屏幕時就不在更改高度防止不斷的繪制,提高性能。
ok,大體思路就這樣。具體分析代碼如下:

實現(xiàn):

activity的xml
stretch_act.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"> <!--這是topView--> <RelativeLayout  android:id="@+id/rl_top"  android:layout_width="match_parent"  android:layout_height="wrap_content"  >  <!--這是imageView,一定要設(shè)置scaleType為centerCrop-->  <ImageView   android:id="@+id/iv_stretch_pic"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:scaleType="centerCrop"   android:src="@drawable/stretch_s"   />  <TextView   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_alignBottom="@id/iv_stretch_pic"   android:text="你最美,你最酷…………^^"   android:textSize="16sp"/> </RelativeLayout><!--這是自定義的listview--> <com.example.zwr.myapplication.widget.StretchListView  android:id="@+id/listview"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:cacheColorHint="@null"  android:divider="@null"  android:listSelector="#00000000"/></LinearLayout>

看看StretchListView:

/***  * @param topView  * @param imgResId 圖片id  */ public void setTopView(View topView, int imgResId) {  if (null != topView) {   this.topView = topView;   imageView = (ImageView) topView.findViewById(imgResId);  } }

通過這個對外的方法,將topView以及ImageView的id傳進(jìn)來

分析:重新ListView的onTouchEvent():

ACTION_DOWN:  case MotionEvent.ACTION_DOWN:    startY = ev.getRawY();    if (!hadInit) {//初始化,只要初始化一次就夠了     childAt0Top = getChildAt(0).getTop();     ivInitHeight = imageView.getHeight();     hadInit = true;    }    break;

只是進(jìn)行一些初始化操作:

 1. startY:相對于屏幕頂部的高度
 2. childAt0Top,獲取listview的第一個view的top距離、
 3. ivInitHeight:獲取ImageView的初始高度,即剛進(jìn)來時的高度
ACTION_MOVE:

case MotionEvent.ACTION_MOVE:    Log.d(TAG, "dy = " + dy);    dy = ev.getRawY() - startY;    if (dy > 0 && 0 == getFirstVisiblePosition() &&     childAt0Top == getChildAt(0).getTop()) {//(1)手指從上往下拉:下拉     int tempDy = (int) (dy + 0.5);     //一定也要給topView增加一定的高度,否則從上啦到下拉就不會顯示     imageView.getLayoutParams().height = imageView.getHeight() + tempDy;     topView.getLayoutParams().height = topView.getHeight() + tempDy;     topView.requestLayout();     isChangedHeight = true;    } else {//(2)手指從下往上拉:上拉     int tempDy = (int) (dy - 0.5);     int currHeight = imageView.getHeight();     float translationY = getNegativeMaxValue(tempDy, -currHeight, 0);     if (translationY <= 0 && currHeight > 0) {      LinearLayout.LayoutParams lp =       (LinearLayout.LayoutParams) topView.getLayoutParams();      //一定要減去titleBar,如果沒有去掉Winow.xxx.Title,還要減去這個高度,否則會顯示不全      lp.height = topView.getHeight() + (int) translationY;      topView.requestLayout();//      isChangedHeight = true;     }    }    //用這個getRawY而不是用getY,是因為listview也會隨著改變,    //而getY獲取的就是listview本身的Y,所以基本是變化不大的,    // 而使用getRawY相對于屏幕的距離,保證滑動了多大的距離就改變多大的距離    startY = ev.getRawY();    break;

當(dāng)下拉時:主要條件如下:

1.dy > 0 && 0 == getFirstVisiblePosition() && childAt0Top ==
getChildAt(0).getTop()
意思是當(dāng)下拉時,并且listview的第一個位置顯示全了,才能下拉放大圖片,這是避免,listview已經(jīng)發(fā)生滾動了,需要回到初始位置才能下拉放大,否則會出現(xiàn),立即下拉放大,體驗不好
2.當(dāng)上拉時 主要條件
if (translationY <= 0 && currHeight > 0)
currHeight>0:當(dāng)前ImageView的高度,如果已經(jīng)滾動到頂部或者超出,則不再進(jìn)行滾動,防止已經(jīng)滾出屏幕不可視了,還在進(jìn)行滾動。
translationY<=0: 這個值是滾動的距離,這個距離不能超過ImageView的高度,由于上拉時dy是負(fù)值,所以要判斷是否小于0;其主要方法如下:

 float translationY = getNegativeMaxValue(tempDy, -currHeight, 0); /***  * 手指上移過程dy是負(fù)數(shù)  * 返回負(fù)數(shù)最大值:0是最大值,不可以超過  *  * @param value   移動的最終距離:上次的位置+當(dāng)次移動的偏移量之和,就是本次要移動的最終的偏移量  * @param canMoveMaxValue 可移動的最大值  * @param maxValue  * @return  */ public static float getNegativeMaxValue(float value,float canMoveMaxValue, float maxValue) {  return Math.min(maxValue, Math.max(canMoveMaxValue, value)); }

ACTION_UP:

case MotionEvent.ACTION_OUTSIDE:   case MotionEvent.ACTION_CANCEL:   case MotionEvent.ACTION_UP:    if (isChangedHeight) {     if (imageView.getHeight() > ivInitHeight) {// (1)手指從上往下拉:下拉      ResetAnimation resetAnimation =       new ResetAnimation(ivInitHeight, imageView, topView);      resetAnimation.setDuration(200);      imageView.startAnimation(resetAnimation);     } else {//(2)手指從下往上拉:上拉。。。這個不用處理。。。因為上拉后松開讓其topview固定     }     isChangedHeight = false;    }    break;

isChangedHeight:當(dāng)發(fā)生ImageView發(fā)生改變,并且是下拉時,這是松開手或者手指移出屏幕,則讓其回彈到初始位置;這里是通過自定義動畫來改變其變化的高度,達(dá)到回彈效果 代碼如下

 /**  * 自定義回彈動畫,使imageView和topView過渡回彈到初始位置  */ static class ResetAnimation extends Animation {  private View topView;  private int topCurrHeight;  private ImageView ivStretch;  private int ivInitHeight;  private int ivCurrHeight;  public ResetAnimation(int ivInitHeiht, ImageView ivStretch, View topView) {   this.ivInitHeight = ivInitHeiht;   this.ivCurrHeight = ivStretch.getHeight();   this.topCurrHeight = topView.getHeight();   this.ivStretch = ivStretch;   this.topView = topView;  }  @Override  protected void applyTransformation(float interpolatedTime, Transformation t) {   int dy = (int) ((ivCurrHeight - ivInitHeight) * interpolatedTime);   Log.d(TAG, "anim dy = " + dy);   ivStretch.getLayoutParams().height = ivCurrHeight - dy;   topView.getLayoutParams().height = topCurrHeight - dy;   topView.requestLayout();  } }

其實主要是applyTransformation(float interpolatedTime, Transformation t) 這個方法

主要是通過這個漸變因子interpolatedTime來控制,其值范圍是(0~1) 所以計算漸變的高度如下
int dy = (int) ((ivCurrHeight - ivInitHeight) * interpolatedTime);
然后一定要記得調(diào)用topView.requestLayout(),讓其重新布局繪制。這樣就完成了,所有代碼,也就一百行代碼左右,是不是很簡單。而且通過這個demo,可以很好的拓展到scrollview中。

注意:
網(wǎng)上有些demo是通過overScrollBy()這個方法中搞事情,因為

/***  * 這個方法是在滑出屏幕時回調(diào),但是由于android系統(tǒng)國內(nèi)廠商修改的面目全非,有些機(jī)型是不會回調(diào)的,比如vivo  * 所以不要使用這個方法搞事情  *  * @param scrollX  * @param scrollY  */ @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,  int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY,  boolean isTouchEvent) {  Log.d(TAG, "deltax = " + deltaX + " deltaY = " + deltaY);  return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,   scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); }

其自帶dy,還有一些其它的參數(shù),應(yīng)有盡有。但是由于android系統(tǒng)是開源的導(dǎo)致有些系統(tǒng)是無法回調(diào)這個方法的,以至于無法實現(xiàn)回彈效果(比如:vivoX5)等等。所以在onTouchEvent()搞事情才是王道
ok!,以上有什么問題,請不吝指正!!!

Demo:android個人主頁下拉回彈

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 廉江市| 新昌县| 天等县| 吴忠市| 融水| 平舆县| 广饶县| 西青区| 北碚区| 昂仁县| 曲周县| 贵溪市| 丹东市| 商都县| 敦煌市| 平陆县| 宜兰县| 芒康县| 新野县| 太仓市| 石棉县| 台前县| 游戏| 杭锦后旗| 新龙县| 广汉市| 隆化县| 兴业县| 贡觉县| 射洪县| 弋阳县| 四子王旗| 科尔| 郎溪县| 涞源县| 绵竹市| 安龙县| 美姑县| 沾化县| 丹阳市| 高安市|