Android之鱼塘开发笔记

1,需求开发一个按照固定轨迹游泳的鱼池

2,实现思路

ViewGroup + ImageView组合,通过定时刷新,不断对子view位置进行摆放处理

  • 2.1,定时刷新采用Handler定时发送消息
  • 2.2,收到消息后调用ViewGrouprequestLayout()触发回调onLayout(boolean changed, int left, int top, int right, int bottom)函数
  • 2.3,重写ViewGroup的onLayout方法,调用子View的layout()函数不断进行位置放.最终形成鱼宠不断游动效果.

3,鱼宠游动轨迹图

device-2021-04-02-103933.png

4,坐标点的测试

P0,
x:990,y:1065
P0x:990, P0y:1065

P1,
x:540,y:572
P1x:540, P1y:572

P2,
x:90,y:572
P2x:90, P2y:572

P3,
x:990,y:80
P3x:990, P3y:80

P4,
x:990,y:572
P4x:990, P4y:572

P5,
x:990,y:80
P5x:990, P5y:990

P6,
x:90,y:80
P6x:90, P6y:80

P7,
x:990,y:572
P7x:990, P7y:572

P8,
x:540,y:572
P8x:540, P8y:572

P9,
x:90,y:1065
P9x:90, P9y:1065

P10,
x:90,y:572
P10x:90, P10y:572

P11,
x:90,y:1065
P11x:90, P11y:1065

P12,
x:990,y:1065
P12x:990, P12y:1065

5,鱼宠游动状态的定义

/**
 * 鱼儿的游动状态
 */
@IntDef({
        FishStatus.UN_KNOW,
        FishStatus.TURN_LEFT,
        FishStatus.TURN_RIGHT,
        FishStatus.MOVE_LEFT,
        FishStatus.MOVE_RIGHT,
})
@Retention(RetentionPolicy.SOURCE)
@interface FishStatus {
    /**
     * 未知状态
     */
    int UN_KNOW = -1;
    /**
     * 向左转
     */
    int TURN_LEFT = 0;
    /**
     * 向右转
     */
    int TURN_RIGHT = 1;
    /**
     * 向左正常游动
     */
    int MOVE_LEFT = 2;
    /**
     * 向右正常游动
     */
    int MOVE_RIGHT = 3;
}

5,对鱼宠游动过程坐标点进行监听,当游动到了路线轨迹坐标点处进行处理并且修改游动状态

  • 5.1坐标点对应鱼宠游动状态分析

  • P0和P12坐标重合
    P0开始向左游动,P12开始向左转身

  • P1和P8坐标重合
    P1,P8分别停留1秒钟

  • P2和P10坐标重合
    P2开始向右转身,P10向下游

  • P3和P5坐标重合
    P3向下游,P5开始向左转身

  • P4和P7坐标重合
    P4开始向上游动,P7开始向左转身,

  • P9和P11坐标重合
    P9开始向上游动,P11开始向右转身

-P6单独坐标点
P6开始向右转身

  • 5.2相邻两坐标点的轨迹的游动状态分析

  • 1,P0--->P1
    向左上方移动

  • 2,P1--->P2
    向左方移动

  • 3,P2--->P3
    向右上方移动

  • 3,P3--->P4
    向下方移动

  • 4,P4--->P5
    向上方移动

  • 5,P5--->P6
    向左方移动

  • 6,P6--->P7
    向右下方移动

  • 7,P7--->P8
    向左方移动

  • 8,P8--->P9
    向左下方移动

  • 9,P9--->P10
    向上方移动

  • 10,P10--->P11
    向下方移动

  • 10,P11--->P12
    向右方移动

  • 5.3如何判断鱼宠坐标点是否在指定的坐标处.

  • 1,鱼宠坐标和P0坐标相等,也和P12坐标相等,不同时刻的路线坐标值存在相同情况,根据坐标值无法判定是否处于指定的坐标处.

  • 2,鱼宠游动方向向左,游动方向由坐标点驱动,无法用于判断是否处于坐标点处.

  • 3,定义private var progress = 0.0F变量,表示移动路线的进度,每个坐标点对应一个进度值.

    • P0,progress=0
    • P12,progress=1
  • 4,如何建立坐标点和路线进度的映射关系

    这里我们采用,keyvalue键值对形式来保存映射关系,用key来表示进度值progress,用value来表示指定坐标点容器索引posotion,
    (0.0,0),(1.0,12),综合分析无法建立较完善的映射关系,该方式无法用来判定是否处于指定坐标处.

  • 5,根据坐标点距离起点的总长度来判定坐标点

    P0:pLength = 0,P1:pLength = (P1.x-P0.x) * (P1.x-P0.x) + (P1.y-P0.y) * (P1.y-P0.y)开根号.

  • 6,根据坐标点范围以及游动状态组合判断

/**
 * 根据移动的坐标点和轨迹坐标点来修改小鱼的游动状态.
 * @param x
 * @param y
 * @param distance 距离起点的直线距离.
 */
private fun onSwimming(x: Float, y: Float, distance: Float) {
    if (pointList.isEmpty()) return

    if (distance == 0F || progress == 0F) {
        //P0,点处开始向左上游动.
        changeSwimming(FishStatus.TURN_LEFT)
        changeSwimming(FishStatus.MOVE_TOP_LEFT)
    }

    if (isInPointRect(pointList[1], x, y)) {
        //P1,P8处停留
        changeSwimming(FishStatus.REST)
    } else {
        when (lastFishStatus) {
            FishStatus.MOVE_TOP_LEFT -> {
                if (fishStatus == FishStatus.REST) {
                    changeSwimming(FishStatus.MOVE_LEFT)
                }
            }

            FishStatus.MOVE_LEFT -> {
                if (fishStatus == FishStatus.REST) {
                    changeSwimming(FishStatus.MOVE_BOTTOM_LEFT)
                }
            }

            else -> {
                when {
                    //P2,P10
                    //P2点处向右转身,开始向右游动.
                    isInPointRect(pointList[2], x, y) -> {
                        //判定该点位于此P2
                        if (fishStatus == FishStatus.MOVE_LEFT) {
                            if (fishStatus != FishStatus.MOVE_TOP_RIGHT) {
                                changeSwimming(FishStatus.TURN_RIGHT)
                                changeSwimming(FishStatus.MOVE_TOP_RIGHT)
                            }
                        }
                        //P10->p11,下游
                        if (fishStatus == FishStatus.MOVE_TOP_ON_LEFT) {
                            changeSwimming(FishStatus.MOVE_BOTTOM_ON_LEFT)
                        }
                    }

                    //P3,P5,
                    isInPointRect(pointList[3], x, y) -> {
                        //P3,下游
                        if (fishStatus == FishStatus.MOVE_TOP_RIGHT) {
                            changeSwimming(FishStatus.MOVE_BOTTOM_ON_RIGHT)
                        }
                        //P5点处向左转身,开始向左游动.
                        if (fishStatus == FishStatus.MOVE_TOP_ON_RIGHT) {
                            changeSwimming(FishStatus.TURN_LEFT)
                            changeSwimming(FishStatus.MOVE_LEFT)
                        }
                    }

                    //P4,P7,
                    isInPointRect(pointList[4], x, y) -> {
                        //P4,上游
                        if (fishStatus == FishStatus.MOVE_BOTTOM_ON_RIGHT) {
                            changeSwimming(FishStatus.MOVE_TOP_ON_RIGHT)
                        }
                        //P7点处向左转身,开始向左游动.
                        if (fishStatus == FishStatus.MOVE_BOTTOM_RIGHT) {
                            changeSwimming(FishStatus.TURN_LEFT)
                            changeSwimming(FishStatus.MOVE_LEFT)
                        }
                    }

                    //P6,
                    isInPointRect(pointList[6], x, y) -> {
                        //P6点处向右转身,开始向右游动.
                        if (fishStatus == FishStatus.MOVE_LEFT) {
                            changeSwimming(FishStatus.TURN_RIGHT)
                            changeSwimming(FishStatus.MOVE_BOTTOM_RIGHT)
                        }
                    }

                    //P9,P11,
                    isInPointRect(pointList[9], x, y) -> {
                        //P9,垂直向上游
                        if (fishStatus == FishStatus.MOVE_BOTTOM_LEFT) {
                            changeSwimming(FishStatus.MOVE_TOP_ON_LEFT)
                        }
                        //P11,向右转身,向右移动
                        if (fishStatus == FishStatus.MOVE_BOTTOM_ON_LEFT) {
                            changeSwimming(FishStatus.TURN_RIGHT)
                            changeSwimming(FishStatus.MOVE_RIGHT)
                        }
                    }
                }
            }
        }
    }
}
  • 5.4鱼宠还正在向左游动就向边转身了的视觉异常处理

  • 6采用SurfaceView方案来增加动画的流畅性.

  • 7动画运行相关参考资料

https://github.com/blipinsk/ViewPropertyObjectAnimator

一款强大的属性动画操作集合
https://github.com/paulyung541/ActionAnimatorSet

小船游动效果
https://github.com/WANZIzZ/RowingView

方块移动,飞机移动
https://github.com/Jetpack-Missionary/MotionChallenge

赛车动画
https://github.com/VKOOY/AnimationRacingCarForKotlin

SurfaceView实现墨迹天气的风车效果
https://blog.csdn.net/xyz_lmn/article/details/20483709

SurfaceView实现下雨与下雪动画效果(Kotlin语法)
https://www.jb51.net/article/123687.htm

SurfaceView实现鱼儿游动动画
https://www.jb51.net/article/138961.htm

SurfaceView实现红包雨平移动画
http://www.zyiz.net/tech/detail-62558.html

Android自定义View实现抖音飘动红心效果
https://www.jb51.net/article/187575.htm

Android十个小案例动画,自定义View动画实现,ValueAnimator
https://blog.csdn.net/u012835548/article/details/53887607

Android属性动画 - 平移动画
https://blog.csdn.net/u010349644/article/details/101151809

https://github.com/heqiangflytosky/AndroidAnimationDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容