当前位置: 移动技术网 > 移动技术>移动开发>Android > Android星球效果实现

Android星球效果实现

2018年10月18日  | 移动技术网移动技术  | 我要评论

 

在项目中看着这个旋转效果挺炫的,就抽取出来做个记录。主要是使用carrousellayout 稍微修改

 

carrousellayout代码demo下载z地址:github

https://github.com/lyfkai/androidcarrousellayout

 

主要代码如下 :

 

public class carrousellayout extends relativelayout {

    private context mcontext;
    //自动旋转 默认不自动
    private boolean mautorotation;

    //旋转间隔时间  默认设置为2秒
    private int mrotationtime;

    //旋转木马旋转半径  圆的半径
    private float mcarrouselr;

    //camera和旋转木马距离
    private float mdistance = 2f * mcarrouselr;

    //旋转方向 分0顺时针和 1逆时针 俯视旋转木马看
    private int mrotatedirection;

    //handler
    private carrouselrotatehandler mhandler;

    //手势处理
    private gesturedetector mgesturedetector;

    //x旋转
    private int mrotationx;

    //z旋转
    private int mrotationz;

    //旋转的角度
    private float mangle = 0;

    //旋转木马子view
    private list<view> mcarrouselviews = new arraylist<>();

    //旋转木马子view的数量
    private int viewcount;

    //半径扩散动画
    private valueanimator manimationr;

    //记录最后的角度 用来记录上一次取消touch之后的角度
    private float mlastangle;

    //是否在触摸
    private boolean istouching;

    //旋转动画
    private valueanimator restanimator;

    //选中item
    private int selectitem;

    //item选中回调接口
    private oncarrouselitemselectedlistener moncarrouselitemselectedlistener;

    //item点击回调接口
    private oncarrouselitemclicklistener moncarrouselitemclicklistener;

    //x轴旋转动画
    private valueanimator xanimation;

    //z轴旋转动画
    private valueanimator zanimation;

    private boolean isfinish = true;//惯性动画是否结束
    private boolean isfling;

    public carrousellayout(context context) {
        this(context, null);
    }

    public carrousellayout(context context, attributeset attrs) {
        this(context, attrs, 0);
    }

    public carrousellayout(context context, attributeset attrs, int defstyleattr) {
        super(context, attrs, defstyleattr);
        init(context, attrs);
    }

    private void init(context context, attributeset attrs) {
        this.mcontext = context;
        typedarray typedarray = context.obtainstyledattributes(attrs, r.styleable.carrousellayout);
        mautorotation = typedarray.getboolean(r.styleable.carrousellayout_autorotation, false);
        mrotationtime = typedarray.getint(r.styleable.carrousellayout_rotationtime, 2000);
        mcarrouselr = typedarray.getdimension(r.styleable.carrousellayout_r, 200);
        mrotatedirection = typedarray.getint(r.styleable.carrousellayout_rotatedirection, 0);
        typedarray.recycle();
        mgesturedetector = new gesturedetector(context, getgesturedetectorcontroller());
        inithandler();
    }

    /**
     * 初始化handler对象
     */
    private void inithandler() {
        mhandler = new carrouselrotatehandler(mautorotation, mrotationtime, mrotatedirection) {
            @override
            public void onrotating(carrouselrotatedirection rotatedirection) {//接受到需要旋转指令
                try {
                    if (viewcount != 0) {//判断自动滑动从那边开始
                        int perangle = 0;
                        switch (rotatedirection) {
                            case clockwise:
                                perangle = 360 / viewcount;
                                break;
                            case anticlockwise:
                                perangle = -360 / viewcount;
                                break;
                        }
                        if (mangle == 360) {
                            mangle = 0f;
                        }

                        if (isfinish)
                            startanimrotation(mangle + perangle, null);
                    }
                } catch (exception e) {
                    e.printstacktrace();
                }

            }
        };
    }


    private gesturedetector.simpleongesturelistener getgesturedetectorcontroller() {

        return new gesturedetector.simpleongesturelistener() {

            @override
            public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) {
                isfling = true;

                if (e2.getx() - e1.getx() < 0) { // 左滑
                    setautoscrolldirection(carrouselrotatedirection.clockwise);
                } else {
                    setautoscrolldirection(carrouselrotatedirection.anticlockwise);
                }
                return true;
            }

            @override
            public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) {
                isfling = false;
                if (distancex > 0) { // 左滑
                    setautoscrolldirection(carrouselrotatedirection.clockwise);
                } else {
                    setautoscrolldirection(carrouselrotatedirection.anticlockwise);
                }
                //转换成弧度
                double radians = math.toradians(mrotationz);
                //math.cos(radians) 返回对应的radians弧度的余弦值
                mangle += math.cos(radians) * (distancex / 4) + math.sin(radians) * (distancey / 4);
                // log.e("mangle", mangle + "");
                log.e("mrotationz", mrotationz + "");
                //初始化
                refreshlayout();
                return true;
            }


        };
    }

    /**
     * 初始化 计算平均角度后各个子view的位置
     */
    public void refreshlayout() {
        for (int i = 0; i < mcarrouselviews.size(); i++) {
            double radians = mangle + 180 - i * 360 / viewcount;
            float x0 = (float) math.sin(math.toradians(radians)) * mcarrouselr;
            float y0 = (float) math.cos(math.toradians(radians)) * mcarrouselr;
            float scale0 = (mdistance - y0) / (mdistance + mcarrouselr);
            mcarrouselviews.get(i).setscalex(scale0 < 0.5f ? 0.5f : scale0);
            mcarrouselviews.get(i).setscaley(scale0 < 0.5f ? 0.5f : scale0);
            if (mcarrouselviews.get(i) instanceof relativelayout) {
                if (((relativelayout) mcarrouselviews.get(i)).getchildcount() >= 2) {
                    if (((relativelayout) mcarrouselviews.get(i)).getchildat(0) instanceof imageview) {
                        int value = float.valueof((scale0 < 0.5f ? 0.5f : scale0) * 255).intvalue();
                        ((imageview) ((relativelayout) mcarrouselviews.get(i)).getchildat(0)).setimagealpha(value);
//                        ((imageview)((relativelayout) mcarrouselviews.get(i)).getchildat(0)).setalpha(scale0);
                    }
//                    ((relativelayout) mcarrouselviews.get(i)).getchildat(0).setalpha(scale0);
                    if (((relativelayout) mcarrouselviews.get(i)).getchildat(1) instanceof textview) {
                        ((relativelayout) mcarrouselviews.get(i)).getchildat(1).setalpha(scale0 < 0.5f ? 0.5f : scale0);
                    }
                }
            }
            float rotationx_y = (float) math.sin(math.toradians(mrotationx * math.cos(math.toradians(radians)))) * mcarrouselr;
            float rotationz_y = -(float) math.sin(math.toradians(-mrotationz)) * x0;
            float rotationz_x = (((float) math.cos(math.toradians(-mrotationz)) * x0) - x0);
            mcarrouselviews.get(i).settranslationx(x0 + rotationz_x);
            mcarrouselviews.get(i).settranslationy(rotationx_y + rotationz_y);
        }
        list<view> arrayviewlist = new arraylist<>();
        arrayviewlist.clear();
        for (int i = 0; i < mcarrouselviews.size(); i++) {
            arrayviewlist.add(mcarrouselviews.get(i));
        }
        sortlist(arrayviewlist);
        postinvalidate();
    }

    /**
     * 排序
     * 對子view 排序,然后根据变化选中是否重绘,这样是为了实现view 在显示的时候来控制当前要显示的是哪三个view,可以改变排序看下效果
     *
     * @param list
     */
    @suppresswarnings("unchecked")
    private <t> void sortlist(list<view> list) {
        @suppresswarnings("rawtypes")
        comparator comparator = new sortcomparator();
        t[] array = list.toarray((t[]) new object[list.size()]);
        arrays.sort(array, comparator);
        int i = 0;
        listiterator<t> it = (listiterator<t>) list.listiterator();
        while (it.hasnext()) {
            it.next();
            it.set(array[i++]);
        }
        for (int j = 0; j < list.size(); j++) {
            list.get(j).bringtofront();
        }
    }

    /**
     * 筛选器
     */
    private class sortcomparator implements comparator<view> {
        @override
        public int compare(view o1, view o2) {
            return (int) (1000 * o1.getscalex() - 1000 * o2.getscalex());
        }
    }


    @override
    protected void onsizechanged(int w, int h, int oldw, int oldh) {
        super.onsizechanged(w, h, oldw, oldh);
        refreshlayout();
        if (mautorotation) {
            mhandler.sendemptymessage(carrouselrotatehandler.mmsgwhat);
        }
    }

    @override
    protected void onlayout(boolean changed, int l, int t, int r, int b) {
        super.onlayout(changed, l, t, r, b);
        if (changed) {
            checkchildview();
            startanimationr();
        }
    }

    /**
     * 旋转木马半径打开动画
     */
    public void startanimationr() {
        startanimationr(1f, mcarrouselr);
    }

    /**
     * 旋转木马半径动画
     *
     * @param isopen 是否打开  否则关闭
     */
    public void startanimationr(boolean isopen) {
        if (isopen) {
            startanimationr(1f, mcarrouselr);
        } else {
            startanimationr(mcarrouselr, 1f);
        }
    }

    /**
     * 半径扩散、收缩动画 根据设置半径来实现
     *
     * @param from
     * @param to
     */
    public void startanimationr(float from, float to) {
        manimationr = valueanimator.offloat(from, to);
        manimationr.addupdatelistener(new valueanimator.animatorupdatelistener() {
            @override
            public void onanimationupdate(valueanimator valueanimator) {
                mcarrouselr = (float) valueanimator.getanimatedvalue();
                refreshlayout();
            }
        });
        manimationr.setinterpolator(new decelerateinterpolator());
        manimationr.setduration(0);
        manimationr.start();
    }

    public void checkchildview() {
        //先清空views里边可能存在的view防止重复
        for (int i = 0; i < mcarrouselviews.size(); i++) {
            mcarrouselviews.remove(i);
        }
        final int count = getchildcount(); //获取子view的个数
        viewcount = count;
        for (int i = 0; i < count; i++) {
            final view view = getchildat(i); //获取指定的子view
            final int position = i;
            mcarrouselviews.add(view);
            view.setonclicklistener(new onclicklistener() {
                @override
                public void onclick(view v) {
                    if (moncarrouselitemclicklistener != null) {
                        moncarrouselitemclicklistener.onitemclick(view, position);
                    }
                }
            });

        }

    }

    /**
     * 复位
     */
    private void restview() {
        if (viewcount == 0) {
            return;
        }
        float resultangle = 0;
        //平均角度
        float averageangle = 360 / viewcount;
        if (mangle < 0) {
            averageangle = -averageangle;
        }
        float minvalue = (int) (mangle / averageangle) * averageangle;//最小角度
        float maxvalue = (int) (mangle / averageangle) * averageangle + averageangle;//最大角度
        if (mangle >= 0) {//分为是否小于0的情况
            if (mangle - mlastangle > 0) {
                resultangle = maxvalue;
            } else {
                resultangle = minvalue;
            }
        } else {
            if (mangle - mlastangle < 0) {
                resultangle = maxvalue;
            } else {
                resultangle = minvalue;
            }
        }
        startanimrotation(resultangle, null);
    }


    /**
     * 动画旋转
     *
     * @param resultangle
     * @param complete
     */
    private void startanimrotation(float resultangle, final runnable complete) {
        if (mangle == resultangle) {
            return;
        }
        if (!isfinish) {
            restanimator = valueanimator.offloat(mangle, mangle + (resultangle - mangle) * 5);
            //设置旋转匀速插值器
            restanimator.setinterpolator(new decelerateinterpolator());
            restanimator.setduration(1000);
        } else {
            restanimator = valueanimator.offloat(mangle, resultangle);
            //设置旋转匀速插值器
            restanimator.setinterpolator(new linearinterpolator());
            restanimator.setduration(8000);
        }

        restanimator.addupdatelistener(new valueanimator.animatorupdatelistener() {
            @override
            public void onanimationupdate(valueanimator animation) {
                if (istouching == false) {
                    mangle = (float) animation.getanimatedvalue();
                    refreshlayout();
                }
            }
        });
        restanimator.addlistener(new animator.animatorlistener() {
            @override
            public void onanimationstart(animator animation) {

            }

            @override
            public void onanimationend(animator animation) {
                if (istouching == false) {
                    selectitem = calculateitem();
                    if (selectitem < 0) {
                        selectitem = viewcount + selectitem;
                    }
                    if (moncarrouselitemselectedlistener != null) {
                        moncarrouselitemselectedlistener.selected(mcarrouselviews.get(selectitem), selectitem);
                    }

                    if (isfinish == false) {
                        isfinish = true;
                    }
                    isfling = false;
                }
            }

            @override
            public void onanimationcancel(animator animation) {

            }

            @override
            public void onanimationrepeat(animator animation) {

            }
        });
        restanimator.start();
    }

    /**
     * 通过角度计算是第几个item
     *
     * @return
     */
    private int calculateitem() {
        return (int) (mangle / (360 / viewcount)) % viewcount;
    }

    /**
     * 触摸停止计时器
     */
    @override
    public boolean dispatchtouchevent(motionevent ev) {
        return setcanautorotation(ev);
    }

    /**
     * 触摸方法
     *
     * @param event
     * @return
     */
    @override
    public boolean ontouchevent(motionevent event) {
        return true;
    }

    /**
     * 触摸时停止自动加载
     *
     * @param event
     */

    float downx = 0;
    float downy = 0;
    long currentms = 0;

    float movex;
    float movey;
    long movetime;


    public boolean setcanautorotation(motionevent event) {

        boolean result = mgesturedetector.ontouchevent(event);
        if (result) {
            this.getparent().requestdisallowintercepttouchevent(true);//通知父控件勿拦截本控件
        }
        if (event.getaction() == motionevent.action_move) {
            if (!result) {
                this.getparent().requestdisallowintercepttouchevent(true);//通知父控件勿拦截本控件
            }
        }


        switch (event.getaction()) {
            case motionevent.action_down:
                mlastangle = mangle;
                downx = event.getx();//float downx
                downy = event.gety();//float downy
                currentms = system.currenttimemillis();//long currentms     获取系统时间

                break;
            case motionevent.action_move:
                movex = event.getx() - downx;//x轴距离
                movey = event.gety() - downy;//y轴距离
                movetime = system.currenttimemillis() - currentms;//移动时间

                if (math.abs(movex) > 50 && movetime > 50) {
                    istouching = true;
                    isfinish = true;

                    stopautorotation();
                }

                break;
            case motionevent.action_up:
            case motionevent.action_cancel:
                if (math.abs(movex) > 50 && movetime > 50) {
                    istouching = false;
                    isfinish = true;
                    if (isfling) {
                        isfinish = false;
                    } else {
                        isfinish = true;
                    }
                    restview();
                    resumeautorotation();
                }
                break;
        }
        return super.dispatchtouchevent(event);
    }

    /**
     * 停止自动加载
     */
    public void stopautorotation() {
        if (mhandler != null && mautorotation) {
            mhandler.removemessages(carrouselrotatehandler.mmsgwhat);
        }
    }

    /**
     * 从新启动自动加载
     */
    public void resumeautorotation() {
        if (mhandler != null && mautorotation) {
            mhandler.sendemptymessagedelayed(carrouselrotatehandler.mmsgwhat, 1000);
        }
    }

    /**
     * 获取所有的view
     *
     * @return
     */
    public list<view> getviews() {
        return mcarrouselviews;
    }

    /**
     * 获取角度
     *
     * @return
     */
    public float getangle() {
        return mangle;
    }


    /**
     * 设置角度
     *
     * @param angle
     */
    public void setangle(float angle) {
        this.mangle = angle;
    }

    /**
     * 获取距离
     *
     * @return
     */
    public float getdistance() {
        return mdistance;
    }

    /**
     * 设置距离
     *
     * @param distance
     */
    public void setdistance(float distance) {
        this.mdistance = distance;
    }

    /**
     * 获取半径
     *
     * @return
     */
    public float getr() {
        return mcarrouselr;
    }

    /**
     * 获取选择是第几个item
     *
     * @return
     */
    public int getselectitem() {
        return selectitem;
    }

    /**
     * 设置选中方法
     *
     * @param selectitem
     */
    public void setselectitem(int selectitem) {
        if (selectitem >= 0) {
            float angle = 0;
            if (getselectitem() == 0) {
                if (selectitem == mcarrouselviews.size() - 1) {
                    angle = mangle - (360 / viewcount);
                } else {
                    angle = mangle + (360 / viewcount);
                }
            } else if (getselectitem() == mcarrouselviews.size() - 1) {
                if (selectitem == 0) {
                    angle = mangle + (360 / viewcount);
                } else {
                    angle = mangle - (360 / viewcount);
                }
            } else {
                if (selectitem > getselectitem()) {
                    angle = mangle + (360 / viewcount);
                } else {
                    angle = mangle - (360 / viewcount);
                }
            }

            float resultangle = 0;
            float part = 360 / viewcount;
            if (angle < 0) {
                part = -part;
            }
            //最小角度
            float minvalue = (int) (angle / part) * part;
            log.e("minvalue", minvalue + "");
            //最大角度
            float maxvalue = (int) (angle / part) * part;

            if (angle >= 0) {//分为是否小于0的情况
                if (angle - mlastangle > 0) {
                    resultangle = maxvalue;
                    log.e("maxvalue", resultangle + "");
                } else {
                    resultangle = minvalue;
                    log.e("maxvalue", resultangle + "");
                }
            } else {
                if (angle - mlastangle < 0) {
                    resultangle = maxvalue;
                } else {
                    resultangle = minvalue;
                }
            }

            if (viewcount > 0) startanimrotation(resultangle, null);
        }
    }

    /**
     * 设置半径
     *
     * @param r
     */
    public carrousellayout setr(float r) {
        this.mcarrouselr = r;
        mdistance = 2f * r;
        return this;
    }

    /**
     * 选中回调接口实现
     *
     * @param moncarrouselitemselectedlistener
     */
    public void setoncarrouselitemselectedlistener(oncarrouselitemselectedlistener moncarrouselitemselectedlistener) {
        this.moncarrouselitemselectedlistener = moncarrouselitemselectedlistener;
    }

    /**
     * 点击事件回调
     *
     * @param moncarrouselitemclicklistener
     */
    public void setoncarrouselitemclicklistener(oncarrouselitemclicklistener moncarrouselitemclicklistener) {
        this.moncarrouselitemclicklistener = moncarrouselitemclicklistener;
    }


    /**
     * 设置是否自动切换
     *
     * @param autorotation
     */
    public carrousellayout setautorotation(boolean autorotation) {
        this.mautorotation = autorotation;
        mhandler.setautorotation(autorotation);
        return this;
    }

    /**
     * 获取自动切换时间
     *
     * @return
     */
    public long getautorotationtime() {
        return mhandler.getmrotationtime();
    }

    /**
     * 设置自动切换时间间隔
     *
     * @param autorotationtime
     */
    public carrousellayout setautorotationtime(long autorotationtime) {
        if (mhandler != null)
            mhandler.setmrotationtime(autorotationtime);
        return this;
    }

    /**
     * 是否自动切换
     *
     * @return
     */
    public boolean isautorotation() {
        return mautorotation;
    }

    /**
     * 设置自动选择方向
     *
     * @param mcarrouselrotatedirection
     * @return
     */
    public carrousellayout setautoscrolldirection(carrouselrotatedirection mcarrouselrotatedirection) {
        if (mhandler != null)
            mhandler.setmrotatedirection(mcarrouselrotatedirection);
        return this;
    }

    public void createxanimation(int from, int to, boolean start) {
        if (xanimation != null) if (xanimation.isrunning() == true) xanimation.cancel();
        xanimation = valueanimator.ofint(from, to);
        xanimation.addupdatelistener(new valueanimator.animatorupdatelistener() {
            @override
            public void onanimationupdate(valueanimator animation) {
                mrotationx = (integer) animation.getanimatedvalue();
                refreshlayout();
            }
        });
        xanimation.setinterpolator(new linearinterpolator());
        xanimation.setduration(2000);
        if (start) xanimation.start();
    }


    public valueanimator createzanimation(int from, int to, boolean start) {
        if (zanimation != null) if (zanimation.isrunning() == true) zanimation.cancel();
        zanimation = valueanimator.ofint(from, to);
        zanimation.addupdatelistener(new valueanimator.animatorupdatelistener() {
            @override
            public void onanimationupdate(valueanimator animation) {
                mrotationz = (integer) animation.getanimatedvalue();
                refreshlayout();
            }
        });
        zanimation.setinterpolator(new linearinterpolator());
        zanimation.setduration(2000);
        if (start) zanimation.start();
        return zanimation;
    }


    public carrousellayout setrotationx(int mrotationx) {
        this.mrotationx = mrotationx;
        return this;
    }

    public carrousellayout setrotationz(int mrotationz) {
        this.mrotationz = mrotationz;
        return this;
    }

    public float getrotationx() {
        return mrotationx;
    }

    public int getrotationz() {
        return mrotationz;
    }

    public valueanimator getrestanimator() {
        return restanimator;
    }

    public valueanimator getanimationr() {
        return manimationr;
    }

    public void setanimationz(valueanimator zanimation) {
        this.zanimation = zanimation;
    }

    public valueanimator getanimationz() {
        return zanimation;
    }

    public void setanimationx(valueanimator xanimation) {
        this.xanimation = xanimation;
    }

    public valueanimator getanimationx() {
        return xanimation;
    }


}

 

handler消息机制控制动态及旋转

 

package com.example.administrator.icome.carrousellayout;


import android.os.handler;
import android.os.message;

/**
 * 旋转木马自动旋转控制handler
 * created by dalong on 2016/11/12.
 */

public abstract class carrouselrotatehandler extends handler {
    //消息what
    public static final int mmsgwhat = 1000;
    //是否旋转
    private boolean isautorotation;
    //旋转事件间隔
    private  long mrotationtime;
    //消息对象
    private message message;
    //旋转方向
    private carrouselrotatedirection  mrotatedirection;

    public carrouselrotatehandler(boolean isautorotation, int mrotationtime , int mrotatedirection) {
        this.isautorotation = isautorotation;
        this.mrotationtime = mrotationtime;
        this.mrotatedirection=mrotatedirection==0?carrouselrotatedirection.clockwise:carrouselrotatedirection.anticlockwise;
        message=createmessage();
        setautorotation(isautorotation);
    }

    /**
     * 消息处理
     * @param msg
     */
    @override
    public void handlemessage(message msg) {
        super.handlemessage(msg);
        switch (msg.what){
            case mmsgwhat:
                //如果自动旋转
                if(isautorotation){
                    //旋转通知
                    onrotating(mrotatedirection);
                    //再次发送消息  循环
                    sendmessage();
                }
                break;
        }
    }

    /**
     * 需要旋转通知方法
     */
    public abstract void onrotating(carrouselrotatedirection mrotatedirection);

    /**
     * 创建消息对象
     * @return
     */
    private message createmessage(){
        message message=new message();
        message.what=mmsgwhat;
        return  message;
    }

    /**
     * 发送消息
     */
    public void sendmessage(){
        //清除所有mmsgwhat的消息
        try {
            removemessages(mmsgwhat);
        } catch (exception e) {
        }
        message=createmessage();
        this.sendmessagedelayed(message,mrotationtime);

    }

    /**
     * 获取是否自动旋转
     * @return
     */
    public boolean isautorotation() {
        return isautorotation;
    }

    /**
     * 设置是否自动旋转
     * @param autorotation
     */
    public void setautorotation(boolean autorotation) {
        isautorotation = autorotation;
        if(autorotation){//如果需要旋转
            sendmessage();
        }else{//不需要旋转  需要清除所有消息队列中的消息
            removemessages(mmsgwhat);
        }
    }

    /**
     * 获取旋转事件间隔
     * @return
     */
    public long getmrotationtime() {
        return mrotationtime;
    }

    /**
     * 设置旋转事件间隔
     * @param mrotationtime
     */
    public void setmrotationtime(long mrotationtime) {
        this.mrotationtime = mrotationtime;
    }

    /**
     * 获取旋转方向
     * @return
     */
    public carrouselrotatedirection getmrotatedirection() {
        return mrotatedirection;
    }

    /**
     * 设置旋转方向
     * @param mrotatedirection
     */
    public void setmrotatedirection(carrouselrotatedirection mrotatedirection) {
        this.mrotatedirection = mrotatedirection;
    }

}

 

 

 

 

 

 

public class carrousellayout extends relativelayout {

private context mcontext;
//自动旋转 默认不自动
private boolean mautorotation;

//旋转间隔时间 默认设置为2秒
private int mrotationtime;

//旋转木马旋转半径 圆的半径
private float mcarrouselr;

//camera和旋转木马距离
private float mdistance = 2f * mcarrouselr;

//旋转方向 分0顺时针和 1逆时针 俯视旋转木马看
private int mrotatedirection;

//handler
private carrouselrotatehandler mhandler;

//手势处理
private gesturedetector mgesturedetector;

//x旋转
private int mrotationx;

//z旋转
private int mrotationz;

//旋转的角度
private float mangle = 0;

//旋转木马子view
private list<view> mcarrouselviews = new arraylist<>();

//旋转木马子view的数量
private int viewcount;

//半径扩散动画
private valueanimator manimationr;

//记录最后的角度 用来记录上一次取消touch之后的角度
private float mlastangle;

//是否在触摸
private boolean istouching;

//旋转动画
private valueanimator restanimator;

//选中item
private int selectitem;

//item选中回调接口
private oncarrouselitemselectedlistener moncarrouselitemselectedlistener;

//item点击回调接口
private oncarrouselitemclicklistener moncarrouselitemclicklistener;

//x轴旋转动画
private valueanimator xanimation;

//z轴旋转动画
private valueanimator zanimation;

private boolean isfinish = true;//惯性动画是否结束
private boolean isfling;

public carrousellayout(context context) {
this(context, null);
}

public carrousellayout(context context

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网