android轮播选中变大,[Android] Gallery选中变大效果的实现

需求:横向滚动的列表,操作类似 Gallery,选中的 Item 居中且放大显示,UI 效果如下图:

9149df5ea106

UI效果示例.jpg

实现方案:

从 API 16 开始,因为效率问题系统控件 Gallery 已被废弃,官方建议使用 HorizontalScrollView 实现,但是根据效果图使用 HorizontalScrollView 实现工作量较大,所以引入了第三方控件:EcoGallery。

1. 重写 EcoGallery 的 getChildStaticTransformation(View, Transformation) 方法:

// View mSelectedChild:记录选中的 Item 的 View

// float mSelectedScale:选中的 Item 放大的倍数

@Override

protected boolean getChildStaticTransformation(View child,

Transformation t) {

if (mSelectedScale != 1.f) {

t.clear();

t.setTransformationType(Transformation.TYPE_MATRIX);

// 判断需要变换的 child 是否为选中的 View

if (child == mSelectedChild) {

// 根据效果图,child 以 (x轴中心、y轴最底部) 为中心点进行缩放

// 设置缩放的中心点横坐标为 child 的 x 轴中心位置

float pivotX = child.getWidth() / 2.f;

// 设置缩放的中心点纵坐标为 child 的 y 轴最底部

float pivotY = child.getHeight() - child.getPaddingBottom();

Matrix matrix = t.getMatrix();

matrix.postScale(mSelectedScale, mSelectedScale,

pivotX, pivotY);

}

}

return true;

}

该实现方案有两个问题:

如果不指定默认选中的 Item,进入页面后第0个 Item 会处于选中状态,之后滚动 Gallery 选中其他的 Item 后,第0个 Item 不会变小,一直显示成放大后的效果,直到再次选中第0个 Item 后才能恢复正常,打印 Log 发现进入页面后从第0个滚动到其他 Item 时 getChildStaticTransformation() 方法中的 child 没有第0个 Item,具体原因未知。

Item 选中后会瞬间变大、变小,体验上不是很好。

因为上面的两个问题,于是放弃了该实现方案。

通过在画 child 之前对 Canvas 进行必要的变换,如上 Transformation 变换类似,重载 drawChild 方法

根据效果图,具体的实现方案思路为:因为 Gallery 选中的 Item 居中显示,所以在绘制 Item 时先计算 Item 和 Gallery 中心点的距离。如果距离=0,此时 Item 应该放大显示,且放大的比例为最大值;列表滚动后,当前放大显示的 Item 远离中心点,放大的比例逐渐变小,而此时列表另一端的 Item 正在接近中心点,显示的比例逐渐变大;当 Item 与中心点的距离超过 Item 的宽度时不再进行放大显示。

// View mSelectedChild:记录选中的 Item 的 View

// float mSelectedScale:选中的 Item 放大的倍数

@Override

protected boolean drawChild(Canvas canvas, View child,

long drawingTime) {

if (mSelectedScale != 1.f) {

// 获取 Item 的 View 的宽度和高度

int childWidth = child.getWidth();

int childHeight = child.getHeight();

// 获取 Gallery 中心点坐标的 x 值

final int center = getCenterOfGallery();

// 获取 Item 中心点坐标的 x 值

final int childCenter = child.getLeft() + childWidth / 2;

// 计算 child 中心点和 Gallery 中心点的距离

final int offsetCenter = Math.abs(center - childCenter);

final float offsetScale = (childWidth - offsetCenter)

* 1.f / childWidth;

// 如果 child 和中心点的距离小于 child 的宽度,此时需要放大显示

if (offsetCenter < childWidth) {

// 设置缩放的中心点坐标

child.setPivotX(childWidth / 2.f);

child.setPivotY(childHeight - child.getPaddingBottom());

// 根据和中心点的距离计算缩放比例

float scale = 1 + (mSelectedScale - 1) * offsetScale;

child.setScaleX(scale);

child.setScaleY(scale);

}

// 如果 child 和中心点的距离不小于 child 的宽度,不需要放大显示

else {

child.setScaleX(1.f);

child.setScaleY(1.f);

}

}

return super.drawChild(canvas, child, drawingTime);

}

最终实现的效果如下图:

9149df5ea106

Gallery最终效果图

参考

源码

开源

最近发现一个比较好的实现方式:使用 ViewPager + ViewPager.PageTransformer,父控件设置 android:clipChildren="false",具体的代码待整理完成后开放出来。

具体实现方式参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值