autojs自定义控件-移动背景

398 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情 >>

牙叔教程 简单易懂

这种移动背景的效果, 怎么做呢?

我们把背景看成一个小球, 小球可以在某个空间内自由移动, 他需要一个目标的坐标信息,

然后需要一个从当前的起点, 到目标点的移动规则,

小球也可以在移动的时候变换形态, 比如圆形, 椭圆, 圆角矩形等

  • 小球可以活动的空间, 我们可以看成是一个父控件, 小球只能在父控件的宽高之内移动;
  • 小球的移动规则, 对应的是加速度, 这个由属性动画控制;
  • 小球的角色是当某个控件的背景, 比如文字控件, 他的半径, 或者说, 宽高, 是由文字控件的宽高决定的

基本分析完成, 我们设计一下对应的接口

  • 父控件有宽高, width, height
  • 小球要移动, 有起点和目标点, startPoint, targetPoint
  • 小球的加速度, 内部用属性动画即可, 需不要暴露接口
  • 小球的宽高, 由文字控件决定, 文字控件的宽高有的一样, 有的不一样, targetViewWidth
  • 未来我们要把小球绑定到导航栏之类的做背景使用, 未来在说未来, 我们先把当前基本的搞好

移动背景的实现方式

有两种

  • 父子控件, 两个控件
  • 单个控件, 内部用canvas绘制

我觉得两个控件消耗大, 我们选择第二种

开始写代码

第一步: 写一个基本的自定义控件

自定义控件的基本方法可以看这篇教程

autojs自定义组件 www.yuque.com/yashujs/bfu…

"ui";
importClass(android.view.View);
var MyView = (function () {
    //继承至ui.Widget
    util.extend(MyView, ui.Widget);
    function MyView() {
        ui.Widget.call(this);
    }
    MyView.prototype.render = function () {
        return <View bg="#ff00ff"></View>;
    };
    ui.registerWidget("my-view", MyView);
    return MyView;
})();

ui.layout(
    <vertical>
        <my-view w="300dp" h="100dp"></my-view>
    </vertical>
);

这就是一个可以设置宽高的基本的自定义控件

第二步: 绘制小球

小球是作为背景来使用, 一般给文字控件做背景, 文字背景的形状基本是圆角矩形

我们来绘制一个圆角矩形

MyView.prototype.drawRoundRect = function (rect, color) {
    color = colors.parseColor(color);
    this.paint.setColor(color);
    let view = this.view;
    let that = this;
    var drawable = new android.graphics.drawable.Drawable({
        draw: function (canvas) {
            var paint = new android.graphics.Paint();
            paint.setColor(color);
            canvas.drawRoundRect(rect, this.rx, this.ry, that.paint);
        },
    });
    view.setBackgroundDrawable(drawable);
};

还差一个rect, 这个rect就是一个矩形, 矩形大小应该包括文字控件,

现在没有文字控件, 所以我们自己构造一个rect,

假设rect的left top right bottom 是(120, 53, 312,168)

MyView.prototype.drawBall = function (left, top, right, bottom, color) {
    let rect = new RectF(left, top, right, bottom);
    this.drawRoundRect(rect, color);
};
MyView.prototype.onFinishInflation = function (view) {
    this.drawBall(120, 53 - status_bar_height, 312, 168 - status_bar_height, "#00ffff");
};

我们在onFinishInflation方法中, 绘制圆角矩形

让小球移动

在不该变矩形大小的情况下, 移动就是修改横坐标的值, 我们来写个move方法,

目前我们没有绑定任何文本控件, 没有具体的移动数值, 就随便写个数字

MyView.prototype.comeAndGo = function (comeLeft, goLeft, color) {
    let top = this.initRect.top;
    let bottom = this.initRect.bottom;
    let that = this;
    let width = this.initRect.right - this.initRect.left;
    var valueAnimator = android.animation.ValueAnimator.ofFloat(comeLeft, goLeft);
    valueAnimator.setDuration(1000);
    valueAnimator.setRepeatCount(ValueAnimator.INFINITE); //无限循环
    valueAnimator.setRepeatMode(ValueAnimator.REVERSE); //ValueAnimator.RESTART(重复),ValueAnimator.REVERSE(反方向重复)
    valueAnimator.setInterpolator(new android.view.animation.AnticipateOvershootInterpolator());
    valueAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener({
            onAnimationUpdate: function (valueAnimator) {
                let value = valueAnimator.getAnimatedValue();
                left = value;
                right = value + width;
                let rect = new RectF(left, top, right, bottom);
                that.drawRoundRect(rect, color);
            },
        })
    );
    valueAnimator.start();
};

调用这个来回动comeAndGo方法, 第一个参数和第二个参数是起点横坐标, 第三个是前景色

this.comeAndGo(60, 300, this.foreColor);

\

这个动画使用的插值器是 AnticipateOvershootInterpolator, 他的效果是

其变化开始向后甩,然后向前甩,过冲到目标值,最后又回到了终值

重复方式是 ValueAnimator.REVERSE,

更多的插值器介绍可以看这个博客:

Android动画之Interpolator(插值器)

blog.csdn.net/pzm1993/art…

那么, 到此为止, 这个会移动的背景, 他的雏形就有了, 改天再拓展

环境

雷电: 4.0.63
Android版本: 7
Autojs版本: 8.8.20

名人名言

思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程\

声明

部分内容来自网络 本教程仅用于学习, 禁止用于其他用途\

微信公众号 牙叔教程