当前位置: 移动技术网 > IT编程>移动开发>Android > Android仿即刻首页垂直滚动图,炫酷到底!

Android仿即刻首页垂直滚动图,炫酷到底!

2019年07月24日  | 移动技术网IT编程  | 我要评论

腐女重生txt下载,三星激光一体机,新型小型工程机械

项目地址:https://github.com/jeasonwong/jikegallery

话不多说,先上效果。

这个效果是在即刻app上看到,觉得很不错,遂仿之。

先说下我的实现思路(以上方的图片滚动为例,下方的文字实现效果类似):

自定义viewgroup
装载两个imageview和一个阴影view
通过一定规律交替控制两个imageview和它们的margintop,在onlayout()中实现
margintop的具体值由属性动画控制,不断调用requestlayout()

接下来依次说明

一、自定义viewgroup

 //滑动状态
 protected static final int status_smoothing = 0;
 //停止状态
 protected static final int status_stop = 1;

 //viewgroup宽高
 protected int mwidth, mheight;
 //变化的margintop值
 protected int msmoothmargintop;
 //默认状态
 protected int mstatus = status_stop;
 //滚动时间间隔
 protected int mduration = 500;
 //重复次数
 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();

 ...

 /**
  * 是否是奇数圈
  *
  * @return 结果
  */
 protected boolean isoddcircle() {
  return mrepeattimes % 2 == 1;
 }

先了解下成员变量,其中最重要的一个就是msmoothmargintop,相信很多人都知道一个view的margintop可以设为负数,这个负数可以给我们带来太多的方便。

上图的图0就是我们展现在屏幕上的imageview,图1则是屏幕外margintop为-height的imageview,这个一定要明白,接下来才好继续实现。

二、装载两个imageview和一个阴影view

 private list<string> mimglist = new arraylist<>();
 private imageview[] mimgs = new imageview[2];
 private view mshadowview;

 ...

 @override
 protected void initview() {

  //如果没有内容,则不进行初始化操作
  if (mimglist.size() == 0) {
   return;
  }

  removeallviews();

  marginlayoutparams params = new marginlayoutparams(mwidth, mheight);

  //两个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]);
  }

  //创建阴影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);
 } 

关键点说明:

marginlayoutparams 为了之后方便取出margin值
addviewinlayout() 为了对requestlayout的绝对控制
getimgpath() 为了实现循环滚动
这样一来,我们需要的view都已经创建好了。

三、通过一定规律交替控制两个imageview和它们的margintop,在onlayout()中实现

 @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);
  }

 }

以上实现的就是不断的替换图1和图2谁上谁下,阴影和下方的图保持同步。

四、margintop的具体值由属性动画控制,不断调用requestlayout()

先看基类viewgroup

 /**
  * 开启滑动
  *
  */
 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;
 }

 //动画结束
 protected abstract void doanimfinish();

 //动画进行时
 protected abstract void doanim();

关键点说明:

属性动画控制着msmoothmargintop在[-mheight, 0]中变化
每完成一圈,mrepeattimes自增1

再来看看gallery实现类

 @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();
 }

关键点说明:

通过msmoothmargintop与mheight的比值控制阴影view的透明度
每次动画完成时,下方的图(此时下方的图已经超出屏幕了,而上方图显示在屏幕内)需要加载第三张图,使用getimgpath()取出
pic1

以上就是图片的滚动实现,文字的滚动90%是一样的,有点区别的就是需要文字需要控制下垂直居中,我就不赘述了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网