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

项目地址: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%是一样的,有点区别的就是需要文字需要控制下垂直居中,我就不赘述了。

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

(0)

相关推荐

  • Android中实现监听ScrollView滑动事件

    时候我们需要监听ScroView的滑动情况,比如滑动了多少距离,是否滑到布局的顶部或者底部.可惜的是SDK并没有相应的方法,不过倒是提供了一个 复制代码 代码如下: protected void onScrollChanged(int x, int y, int oldx, int oldy) 方法,显然这个方法是不能被外界调用的,因此就需要把它暴露出去,方便使用.解决方式就是写一个接口, 复制代码 代码如下: package com.example.demo1;    public inter

  • 在android中ScrollView嵌套ScrollView解决方案

    大家好,众所周知,android里两个相同方向的ScrollView是不能嵌套的,那要是有这样的需求怎么办?(这个需求一般都是不懂android的人提出来的) 难道就真的不能嵌套吗?当然可以,只要你再写一个ScrollView,在里面做点脚,它就支持嵌套了. 目前做的这个只支持两个ScrollView嵌套,两个以上还有待改进,能套两个就已经能满足很多需求了,呵呵,另外现在只做了纵向scrollview的支持,横向的还没来的急做哦. 效果截图:  先上核心代码吧.代码里头我加了注释,方便大家阅读

  • Android TextView实现垂直滚动效果的方法

    本文实例讲述了Android TextView实现垂直滚动效果的方法.分享给大家供大家参考,具体如下: 在TextView中,如果文本很长,可能需要实现垂直滚动显示文本的效果.这里需要在XML布局文件中为TextView设置如下几个属性. Android:scrollbars="vertical" android:scrollbarStyle="X" 其中X为outsideOverlay或insideOverlay. android:scrollbarFadeDur

  • Android之ScrollView嵌套ListView和GridView冲突的解决方法

    那么里面的ScrollView高度计算就会出现问题.我们也就无法得到想要的效果.核心解决方案: 重写ListView或者GridView的OnMesure 方法. 复制代码 代码如下: public class MyListView extends ListView {        public MyListView(Context context) {                super(context);        }        public MyListView(Conte

  • android TextView不用ScrollViewe也可以滚动的方法

    代码 复制代码 代码如下: TextView textview = (TextView) findViewById(R.id.text);            /**             *              * 只有调用了该方法,TextView才能不依赖于ScrollView而实现滚动的效果.             * 要在XML中设置TextView的textcolor,否则,当TextView被触摸时,会灰掉.             */ textview.setMov

  • android 实现ScrollView自动滚动的实例代码

    有时候需要动态添加数据,屏幕显示满了,数据需要滚动展示.这里主要弄懂scrollTo(0, off)方法的含义喊用法. 含义不说了,大概意思就这样. 下面来看他的用法: 复制代码 代码如下: private void searchResultShow() { TextView textView = new TextView(AFSearchActivity.this);           textView.setText("Text View ");           Linear

  • android开发教程之文本框加滚动条scrollview

    我们都知道EditText与TextView是Android的文本输入框和文本显示框,但是基于手机屏幕的大小因素,如果在需要输入较多文字或者显示较多内容的时候,手机屏幕是远远不够的,因此让文本框具有滚动条的功能是手机上必备的,下面介绍下如何加上滚动条.要加上滚动条,其实很简单,只需要在文本输入框或者文本显示框上面加上滚动条控件即可,该控件名字为ScrollView,以下我们对比下(以TextView举例). 复制代码 代码如下: //A.未加滚动效果 <TextView android:layo

  • Android实现Activity水平和垂直滚动条的方法

    本文实例讲述了Android实现Activity水平和垂直滚动条的方法.分享给大家供大家参考,具体如下: <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="

  • Android垂直滚动控件ScrollView使用方法详解

    一.简介 二.方法 1)ScrollView垂直滚动控件使用方法 1.在layout布局文件的最外层建立一个ScrollView控件 2.在ScrollView控件中加入一个LinearLayout控件,并且把它的orientation设置为vertical 3.在LinearLayout控件中放入多个装有图片的ImageView控件 三.代码实例 1.效果图 2.代码 /Ex27ScrollView/src/fry/Activity01.java <?xml version="1.0&q

  • android 自定义ScrollView实现背景图片伸缩的实现代码及思路

       用过多米音乐的都市知道, 这个UI可以上下滑动,作用嘛---无聊中可以划划解解闷,这被锤子公司老罗称谓为"情怀",其实叫"情味"更合适.嘿嘿.如今挪动互联网开展这么迅速,市场上已不再是那早期随便敲个APP放上架就能具有几十万用户的阶段了.近来苹果公司,为了怕android下载量赶超苹果商店,大势宣称:(第 500 亿个下载应用的用户就能够获得 10,000 美元的 iTunes 礼品卡,除此之外,紧随第 500 亿以后的前 50 名用户也可以获得 500 美元

随机推荐