手机
当前位置:查字典教程网 >编程开发 >安卓软件开发 >Android仿即刻首页垂直滚动图
Android仿即刻首页垂直滚动图
摘要:Android仿即刻首页垂直滚动图这个效果是在即刻app上看到,觉得很不错,遂仿之。先说下我的实现思路(以上方的图片滚动为例,下方的文字实现...

Android仿即刻首页垂直滚动图

Android仿即刻首页垂直滚动图1

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

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

自定义ViewGroup

装载两个ImageView和一个阴影View

通过一定规律交替控制两个ImageView和它们的marginTop,在onLayout()中实现

marginTop的具体值由属性动画控制,不断调用requestLayout()

接下来依次说明

一、自定义ViewGroup

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//滑动状态
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
private List 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()中实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 开启滑动
*
*/
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实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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%是一样的,有点区别的就是需要文字需要控制下垂直居中,我就不赘述了。

【Android仿即刻首页垂直滚动图】相关文章:

Android 取得状态栏、任务栏高度的小例子

干货!Android最好用的第三方开源库锦集

Android Studio使用教程图文详解

android项目打包jar

Android Mms之:草稿管理的应用

Android adb shell命令合集

android ListView的右边滚动滑块启用方法 分享

Android开发常用小功能

Android开发之实现手指直接拖动图片移动

Android HTTP 实现与服务器通信

精品推荐
分类导航