zoukankan      html  css  js  c++  java
  • 仿即刻app"猜你喜欢"切换控件

         最近在即刻里看到即刻的"猜你喜欢"的板块,觉得效果很赞。

         

        

        当点击"换一换"时,上面三个条目程序切换效果,并且三个条目的切换以不同的速度进行。

        于是开始想办法撸出这样的切换效果。

        我的思路是使用竖直切换的ViewPager,因为之前使用过ViewPager的一些切换动画和这里的切换很相似。

        最后实现的两种效果:

                   

         

        github地址点我  

        关于竖直切换的ViewPager,你能找到很多资料,我这里使用的是一个日本小哥的VerticalViewPager

        他在onInterceptTouchEvent方法里巧妙的添加了swapTouchEvent方法,将左右滑动切换转换为上下滑动,或者说当你上下滑动时,造成一个假象,viewpager以为你在上下切换。

       

    package com.example.xw.jikeviewpager;
    
    /**
     * Created by xw on 2016/10/9.
     */
    
    import android.content.Context;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    
    import Transformer.DefaultTransformer;
    
    
    public class VerticalViewPager extends ViewPager {
    
        public VerticalViewPager(Context context) {
            this(context, null);
        }
    
        public VerticalViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
            setPageTransformer(false, new DefaultTransformer());
        }
    
        private MotionEvent swapTouchEvent(MotionEvent event) {
            float width = getWidth();
            float height = getHeight();
    
            float swappedX = (event.getY() / height) * width;
            float swappedY = (event.getX() / width) * height;
    
            event.setLocation(swappedX, swappedY);
    
            return event;
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            boolean intercept = super.onInterceptTouchEvent(swapTouchEvent(event));
            //If not intercept, touch event should not be swapped.
            swapTouchEvent(event);
            return intercept;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            return super.onTouchEvent(swapTouchEvent(ev));
        }
    
    }
    

       关于DefaultTransformer类,是用来控制切换效果的,接下来我们会用ZoomOutTransformer。

       关于这几个类,代码点我

       接下来发现即刻切换中的图片都是圆角矩形,关于自定义一个圆角矩形ImageView,代码如下,具体就不分析了。

       

    public class RoundRectImageView extends ImageView{
    
        private Paint paint;
    
        public RoundRectImageView(Context context) {
            this(context,null);
        }
    
        public RoundRectImageView(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public RoundRectImageView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            paint  = new Paint();
        }
    
        /**
         * 绘制圆角矩形图片
         * @author caizhiming
         */
        @Override
        protected void onDraw(Canvas canvas) {
    
            Drawable drawable = getDrawable();
            if (null != drawable) {
                Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
                Bitmap b = getRoundBitmap(bitmap, 20);
                final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
                final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
                paint.reset();
                canvas.drawBitmap(b, rectSrc, rectDest, paint);
    
            } else {
                super.onDraw(canvas);
            }
        }
    
        /**
         * 获取圆角矩形图片方法
         * @param bitmap
         * @param roundPx,一般设置成14
         * @return Bitmap
         * @author caizhiming
         */
        private Bitmap getRoundBitmap(Bitmap bitmap, int roundPx) {
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                    bitmap.getHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
    
            final int color = 0xff424242;
    
            final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            final RectF rectF = new RectF(rect);
            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(color);
            int x = bitmap.getWidth();
    
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
            paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
            canvas.drawBitmap(bitmap, rect, rect, paint);
            return output;
    
    
        }
    }
    

         

        接下来我们实现第一种切换效果,以一个RoundRectImageView加textview作为fragment,然后将fragment作为VerticalViewPager的内容。

        fragment_item.xml   

        

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="130dp"
                  android:layout_height="130dp">
        <com.example.xw.jikeviewpager.RoundRectImageView
            android:id="@+id/iv"
            android:scaleType="centerCrop"
            android:layout_width="match_parent"
            android:layout_height="120dp"/>
    
       <TextView
           android:id="@+id/tv"
           android:text="1111"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>
    
    </LinearLayout>
    

        创建fragment类和一个item的实体类代码就省略了。

        要注意这里利用 Argument传数据生成fragment。

       public static MyFragment newInstance(int imgId,String text){
            Bundle args=new Bundle();
            args.putSerializable(ARG_IMG_ID,imgId);
            args.putSerializable(ARG_TEXT,text);
    
            MyFragment fragment=new MyFragment();
            fragment.setArguments(args);
            return fragment;
    
        }
    

         接下来在MainActivity中,我们的布局使用两个VerticalViewPager和一个负责切换的button。

        

    private void initViewPager() {
    
    
           int[] ims={R.drawable.kenan,R.drawable.mingren,R.drawable.lufei};
            String[] text={"身体虽然变小,但头脑依然灵活",
                    "卡 给 分 新 诺 句 子 !!!",
                    "我是要成为海贼王的男人!"};
            for (int i = 0; i <ims.length ; i++) {
                Item item=new Item(ims[i],text[i]);
                list.add(item);
            }
    
            int[] ims2={R.drawable.qinnv,R.drawable.yasuo,R.drawable.timo};
            String[] text2={
                "为什么哑巴琴女会说话?",
                "死亡如风,常伴吾身",
                    "timo队长,正在送命"
            };
            for (int i = 0; i <ims2.length ; i++) {
                Item item=new Item(ims2[i],text2[i]);
                list2.add(item);
            }
    
            viewPager.setPageTransformer(true, new ZoomOutTransformer());
            viewPager2.setPageTransformer(true,new ZoomOutTransformer());
    
            //viewPager.setPageTransformer(true, new StackTransformer());
            FragmentManager fm=getSupportFragmentManager();
            viewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
                @Override
                public Fragment getItem(int position) {
                    Item item=list.get(position);
                    return MyFragment.newInstance(item.getImageId(),item.getText());
                }
    
                @Override
                public int getCount() {
                    return list.size();
                }
            });
            viewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
            viewPager.setCurrentItem(list.size()-1);
    
            viewPager2.setAdapter(new FragmentStatePagerAdapter(fm) {
                @Override
                public Fragment getItem(int position) {
                    Item item=list2.get(position);
                    return MyFragment.newInstance(item.getImageId(),item.getText());
                }
    
                @Override
                public int getCount() {
                    return list2.size();
                }
            });
    
            viewPager2.setOverScrollMode(View.OVER_SCROLL_NEVER);
            viewPager2.setCurrentItem(list.size()-1);
        }
    

        因为我们用的是ZoomOut的效果,所以先设置显示在最后一页,点击button时,设置位置减1,刚好可以实现往下切换的效果。

       (其实是因为没有找到ZoomIn的类,如果你找到了直接使用这个转换效果类即可)

       

    changeButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                        viewPager.setCurrentItem((viewPager.getCurrentItem()-1));
                        viewPager2.setCurrentItem(viewPager2.getCurrentItem()-1);
                }
            });
    

        最后,还要实现的是两边切换速度不一样,因为viewPager.setCurrentItem方法设施的切换总是一闪而过,太短暂了,无法形成视觉停留的效果。

        这时候需要用到的类

        FixedSpeedScroller

        

    public class FixedSpeedScroller extends Scroller {
        private int mDuration = 1500;
    
        public FixedSpeedScroller(Context context) {
            super(context);
        }
    
        public FixedSpeedScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }
    
        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }
    
        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }
    
        public void setmDuration(int time) {
            mDuration = time;
        }
    
        public int getmDuration() {
            return mDuration;
        }
        public void initViewPagerScroll(ViewPager viewPager) {
            try {
                Field mScroller = ViewPager.class.getDeclaredField("mScroller");
                mScroller.setAccessible(true);
                mScroller.set(viewPager, this);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    

        这里我们看到是利用的反射的手法修改viewpager的"mScroller"字段。

        MainActivity中初始化时调用

        

        private void initSpeed() {
            FixedSpeedScroller scroller=new FixedSpeedScroller(this);
            scroller.setmDuration(2500);
            scroller.initViewPagerScroll(viewPager);
    
            FixedSpeedScroller scroller2=new FixedSpeedScroller(this);
            scroller2.setmDuration(1500);
            scroller2.initViewPagerScroll(viewPager2);
        }
    

         这时候就已经完成了不同的切换速度。

         效果:

        

        至于第二种文字单独切换的,只要将文字单独用一个VerticalViewPager即可。

        以上方法仅供参考,实际应用的话肯定还是要不断地优化处理。

      

        

        

         

      

  • 相关阅读:
    Bash : 冒泡排序
    Azure Load Balancer : 支持 IPv6
    Azure Load Balancer : 简介
    sudo 与输出重定向
    Linux lsof 命令
    Bash : IO 重定向
    LVM : 快照
    2014年全年总结
    使用Kindle4rss推送自己感兴趣的博文
    换SSD硬盘,重装系统,一阵子忙乱
  • 原文地址:https://www.cnblogs.com/xurui1995/p/5947032.html
Copyright © 2011-2022 走看看