亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android仿即刻首頁(yè)垂直滾動(dòng)圖,炫酷到底!

 更新時(shí)間:2016年09月09日 11:26:00   作者:jeasonwong  
這篇文章主要為大家詳細(xì)介紹了Android仿即刻首頁(yè)垂直滾動(dòng)圖效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

項(xiàng)目地址:https://github.com/JeasonWong/JikeGallery

話不多說(shuō),先上效果。

這個(gè)效果是在即刻app上看到,覺得很不錯(cuò),遂仿之。

先說(shuō)下我的實(shí)現(xiàn)思路(以上方的圖片滾動(dòng)為例,下方的文字實(shí)現(xiàn)效果類似):

自定義ViewGroup
裝載兩個(gè)ImageView和一個(gè)陰影View
通過一定規(guī)律交替控制兩個(gè)ImageView和它們的marginTop,在onLayout()中實(shí)現(xiàn)
marginTop的具體值由屬性動(dòng)畫控制,不斷調(diào)用requestLayout()

接下來(lái)依次說(shuō)明

一、自定義ViewGroup

 //滑動(dòng)狀態(tài)
 protected static final int STATUS_SMOOTHING = 0;
 //停止?fàn)顟B(tài)
 protected static final int STATUS_STOP = 1;

 //ViewGroup寬高
 protected int mWidth, mHeight;
 //變化的marginTop值
 protected int mSmoothMarginTop;
 //默認(rèn)狀態(tài)
 protected int mStatus = STATUS_STOP;
 //滾動(dòng)時(shí)間間隔
 protected int mDuration = 500;
 //重復(fù)次數(shù)
 protected int mRepeatTimes = 0;

 ...

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  mWidth = w;
  mHeight = h;
  mSmoothMarginTop = -h;
  initView();
 }

 protected abstract void initView();

 ...

 /**
  * 是否是奇數(shù)圈
  *
  * @return 結(jié)果
  */
 protected boolean isOddCircle() {
  return mRepeatTimes % 2 == 1;
 }

先了解下成員變量,其中最重要的一個(gè)就是mSmoothMarginTop,相信很多人都知道一個(gè)View的marginTop可以設(shè)為負(fù)數(shù),這個(gè)負(fù)數(shù)可以給我們帶來(lái)太多的方便。

上圖的圖0就是我們展現(xiàn)在屏幕上的ImageView,圖1則是屏幕外marginTop為-height的ImageView,這個(gè)一定要明白,接下來(lái)才好繼續(xù)實(shí)現(xiàn)。

二、裝載兩個(gè)ImageView和一個(gè)陰影View

 private List<String> mImgList = new ArrayList<>();
 private ImageView[] mImgs = new ImageView[2];
 private View mShadowView;

 ...

 @Override
 protected void initView() {

  //如果沒有內(nèi)容,則不進(jìn)行初始化操作
  if (mImgList.size() == 0) {
   return;
  }

  removeAllViews();

  MarginLayoutParams params = new MarginLayoutParams(mWidth, mHeight);

  //兩個(gè)ImageView加載前兩張圖
  for (int i = 0; i < mImgs.length; i++) {
   mImgs[i] = new ImageView(getContext());
   addViewInLayout(mImgs[i], -1, params, true);
   Glide.with(getContext()).load(getImgPath(i)).centerCrop().into(mImgs[i]);
  }

  //創(chuàng)建陰影View
  mShadowView = new View(getContext());
  mShadowView.setBackgroundColor(Color.parseColor("#60000000"));
  mShadowView.setAlpha(0);
  addViewInLayout(mShadowView, -1, params, true);
 }

 ...

 /**
  * 獲取圖片地址
  * 
  * @param position 位置
  * @return 圖片地址
  */
 private String getImgPath(int position) {
  position = position % mImgList.size();
  return mImgList.get(position);
 } 

關(guān)鍵點(diǎn)說(shuō)明:

MarginLayoutParams 為了之后方便取出margin值
addViewInLayout() 為了對(duì)requestLayout的絕對(duì)控制
getImgPath() 為了實(shí)現(xiàn)循環(huán)滾動(dòng)
這樣一來(lái),我們需要的View都已經(jīng)創(chuàng)建好了。

三、通過一定規(guī)律交替控制兩個(gè)ImageView和它們的marginTop,在onLayout()中實(shí)現(xiàn)

 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {

  int cCount = getChildCount();
  MarginLayoutParams cParams;

  for (int i = 0; i < cCount; i++) {
   View childView = getChildAt(i);
   cParams = (MarginLayoutParams) childView.getLayoutParams();

   int cl = 0, ct = 0, cr, cb;

   if (isOddCircle()) {
    if (i == 1) {
     cl = cParams.leftMargin;
     ct = mSmoothMarginTop + mHeight;
    } else if (i == 0) {
     cl = cParams.leftMargin;
     ct = mSmoothMarginTop;
    }
   } else {
    if (i == 0) {
     cl = cParams.leftMargin;
     ct = mSmoothMarginTop + mHeight;
    } else if (i == 1) {
     cl = cParams.leftMargin;
     ct = mSmoothMarginTop;
    }
   }
   //控制shadowView
   if (i == 2) {
    cl = cParams.leftMargin;
    ct = mSmoothMarginTop + mHeight;
   }

   cr = cl + mWidth;
   cb = ct + mHeight;
   childView.layout(cl, ct, cr, cb);
  }

 }

以上實(shí)現(xiàn)的就是不斷的替換圖1和圖2誰(shuí)上誰(shuí)下,陰影和下方的圖保持同步。

四、marginTop的具體值由屬性動(dòng)畫控制,不斷調(diào)用requestLayout()

先看基類ViewGroup

 /**
  * 開啟滑動(dòng)
  *
  */
 public void startSmooth() {

  if (mStatus != STATUS_STOP) {
   return;
  }

  ValueAnimator animator = ValueAnimator.ofFloat(-mHeight, 0);
  animator.setDuration(mDuration);
  animator.setInterpolator(new AccelerateDecelerateInterpolator());
  animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator animation) {

    float marginTop = (float) animation.getAnimatedValue();
    mSmoothMarginTop = (int) marginTop;

    if (marginTop == 0) {

     postDelayed(new Runnable() {
      @Override
      public void run() {

       mRepeatTimes++;

       mSmoothMarginTop = -mHeight;

       doAnimFinish();

       mStatus = STATUS_STOP;

      }
     }, 50);

    } else {
     doAnim();
    }
   }
  });
  animator.start();
  mStatus = STATUS_SMOOTHING;
 }

 //動(dòng)畫結(jié)束
 protected abstract void doAnimFinish();

 //動(dòng)畫進(jìn)行時(shí)
 protected abstract void doAnim();

關(guān)鍵點(diǎn)說(shuō)明:

屬性動(dòng)畫控制著mSmoothMarginTop在[-mHeight, 0]中變化
每完成一圈,mRepeatTimes自增1

再來(lái)看看Gallery實(shí)現(xiàn)類

 @Override
 protected void doAnimFinish() {
  if (isOddCircle()) {
   Glide.with(getContext()).load(getImgPath(mRepeatTimes + 1)).centerCrop().into(mImgs[0]);
  } else {
   Glide.with(getContext()).load(getImgPath(mRepeatTimes + 1)).centerCrop().into(mImgs[1]);
  }
  mShadowView.setAlpha(0);
 }

 @Override
 protected void doAnim() {
  mShadowView.setAlpha(((1 - (-mSmoothMarginTop) / (float) mHeight)));
  requestLayout();
 }

關(guān)鍵點(diǎn)說(shuō)明:

通過mSmoothMarginTop與mHeight的比值控制陰影View的透明度
每次動(dòng)畫完成時(shí),下方的圖(此時(shí)下方的圖已經(jīng)超出屏幕了,而上方圖顯示在屏幕內(nèi))需要加載第三張圖,使用getImgPath()取出
pic1

以上就是圖片的滾動(dòng)實(shí)現(xiàn),文字的滾動(dòng)90%是一樣的,有點(diǎn)區(qū)別的就是需要文字需要控制下垂直居中,我就不贅述了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論