几行代码搞定画廊效果

这篇博客介绍了如何使用代码创建一个本地图片加载的画廊效果,包括如何处理RecyclerView的横向滑动,以及在点击时避免动画错乱的问题。博主通过自定义View和RecyclerView Adapter实现了画廊效果,并使用反射技术来控制RecyclerView的滑动。
摘要由CSDN通过智能技术生成

曲木为直终必弯,养狼当犬看家难。墨染鸬鹚黑不久,粉刷乌鸦白不坚。蜜饯黄莲终需苦,强摘瓜果不能甜。好事总得善人做,哪有凡人做神仙。
当!
废话不多言,上回书说道,我最近寻思干点嘛,却又无所事事,天天水群,于是心不安理不得,这天忽然看到一个画廊效果,虽然已是过时产物,但是本着劳资不会,就是比比的崇高目标,结果遭人鄙视,无人同情,令人叹惋。
alone
于是乎,奋笔疾书,瞎(说鸡不说吧,文明你我他)写,终于在某年某月某时某分拼凑出来,效果如下:
这就是效果咯
因为做的是本地图片加载的画廊效果,在加载网络图片时会有一定的闪屏,文末也会给大家提供解决方法,但本例写的时候开始使用的是本地图片。
首先我们拿到布局,应该想到,上面的大图应该是一个ImageView,而下面是一个可横向滑动View,因为横向滑动的View并没有多少选择,所以这里我选择了recyclerView,这里看基本的布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <test.com.xiaomamenu.RectImageView
            android:layout_width="match_parent"
            android:layout_weight="1"
            android:layout_height="200dp"
            android:transitionName="translate"
            android:id="@+id/second_img"
            android:layout_margin="30dp"
            android:scaleType="centerCrop"
            />
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/second_rv"
            ></android.support.v7.widget.RecyclerView>

    </LinearLayout>

</FrameLayout>

这个RectImageView继承了ImageView,在onmeaure的时候使高度和宽度相等,这个非常简单,这里就不提了,实在不会的可以使用ImageView高度宽度相等即可。
这里应该注意一点,最外层的view必须是FrameLayout,因为我们后面会根据FrameLayout的特性进行动画的操作。
接下来,我们定义一个RecyclerView的Adapter,这里只是代码演示,所以代码比较粗糙,勿怪。

 rv.setLayoutManager(new LinearLayoutManager(SecondActivity.this, LinearLayoutManager.HORIZONTAL, false));

        rv.setAdapter(new RecyclerView.Adapter<SecondActivity.VH>() {
            @Override
            public SecondActivity.VH onCreateViewHolder(ViewGroup parent, int viewType) {
                return new SecondActivity.VH(LayoutInflater.from(SecondActivity.this).inflate(R.layout.new_item, parent, false));
            }

            @Override
            public void onBindViewHolder(final SecondActivity.VH holder, final int position) {
            //holder.img.setImageResource(imgs.get(position));
                Glide.with(SecondActivity.this).load(imgs.get(position)).dontAnimate().dontTransform().diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.img);
            }
               @Override
            public int getItemCount() {
                return imgs.size();
            }
    });

这样我们非常质朴的Adapter就写出来了,首先我们根据图片应该联想到,两张图片对换,那么我们肯定需要list 和 大图资源数据的对换,这样我们需要一个变量来解决这个问题。
接下来我们开始构造方法,首先我希望可以通过单例的形式实现点击的时候动画交互效果,这样能有效的节约资源和内存,那么首先我们先无脑new出来一个utils先。

public class AnimatorUtils<T> {
  private static AnimatorUtils utils;
    public static AnimatorUtils getInstance() {
        if (null == utils) {
            synchronized (AnimatorUtils.class) {
                if (null == utils) {
                    utils = new AnimatorUtils();
                }
            }
        }
        return utils;
    }

}

这样我们构造出了一个单例模式,然后我们开始写具体的方法,首先我们肯定需要知道和我们交互的itemView和ImageView,然后我们还需要context上下文来获取根布局以及一些其他的操作,还有List数据,当前itemView的position位置,以及大图的资源文件,因为大图的资源文件未知,所以我这里使用了泛型,我们大概就只需要这么多的参数,好了,接下来开始大段的代码,代码上都写了注释,所以应该很容易理解。

  //获取当前activity下的根布局
        ViewGroup vp= (ViewGroup) ((Activity)context).findViewById(android.R.id.content);
        ViewGroup rootView = (ViewGroup) vp.getChildAt(0);
        if (!((rootView instanceof RelativeLayout) || (rootView instanceof FrameLayout))) {
            throw new IllegalArgumentException("关掉重试,换换运气");
        }

        //获取target的宽高
        translateViewWidth = translateView.getWidth();
        translateViewHeight = translateView.getHeight();
        if (translateViewWidth <= 0 || translateViewHeight <= 0) {
            throw new IllegalArgumentException("建议你删代码跑路");
        }
        //获取itemView的宽高
        itemWidth = itemView.getWidth();
        itemHeight = itemView.getHeight();
        if (itemWidth <= 0 || itemHeight <= 0) {
            throw new IllegalArgumentException("我已经删掉了android studio");
        }
        //获取itemView所在的位置
        itemView.getLocationInWindow(itemViewLocation);
        //获取target所在位置
        translateView.getLocationInWindow(translateViewLocation);
        //获取状态栏高度
        int statusHeight = getStatusHeight();

不要在意我throw错误的那些细节,那些都只是我痛苦血泪之后的真实。
我们获取了一些必要的参数,比如当前itemView和ImageView在window中的位置,这样才能做动画的参数值,但是该怎么样做动画呢,首先属性动画虽然能改变view的属性,但是并不能改变view在当前层级的位置,所以我们并不能直接操作itemView和ImageView,这样我们就只剩下一条路了,造假!
于是乎,乎如是,一个又low又2又弱鸡的方案就诞生了。

  //第一次add进来
        if (translateViewBitmap == null) {
            translateViewBitmap = new ImageView(context);
            rootView.addView(translateViewBitmap);

            lp2 = (FrameLayout.LayoutParams) translateViewBitmap.getLayoutParams();
            if (lp2 != null) {
                lp2.width = translateViewWidth;
                lp2.height = translateViewHeight;
                lp2.setMargins(translateViewLocation[0], translateViewLocation[1] - statusHeight, 0, 0);
            } else {
                lp2 = new FrameLayout.LayoutParams(translateViewWidth, translateViewHeight);
                lp2.setMargins(translateViewLocation[0], translateViewLocation[1] - statusHeight, 0, 0);
            }
            translateViewBitmap.setLayoutParams(lp2);
        } else {
            translateViewBitmap.setVisibility(View.VISIBLE);
            translateViewBitmap.setScaleX(1);
            translateViewBitmap.setScaleY(1);
            translateViewBitmap.setTranslationX(0);
            translateViewBitmap.setTranslationY(0);
            lp2
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值