主頁 > 移動端開發 > Android 屬性影片

Android 屬性影片

2020-09-11 12:09:45 移動端開發

一、ValueAnimator

ValueAnimator是值的變動,可以控制控制元件的一些值,從而達到變化影片的效果,


    public void doAnimation() {
//        final ValueAnimator valueAnimatorInt = ValueAnimator.ofInt(0,400,100,555,250);
        //輸入需要變化的值,是個變化的陣列,可以有int型別和float型別
        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f,400.0f,100.0f,555.0f,250.0f);
        valueAnimator.setDuration(9000);//影片持續時間
        //監聽影片的變化時間,在變化中對控制元件進行操作,也可以通過handle來做一些有趣的事情
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //獲得變化的值
                Float curValueFloat = (Float) valueAnimator.getAnimatedValue();
                //設定為整型
                int curValue = https://www.cnblogs.com/lanjiabin/p/curValueFloat.intValue();
                //改變控制元件的位置,layout對應的是控制元件的位置
                valueTV.layout(curValue, curValue, curValue + imageView.getWidth(), curValue + imageView.getHeight());
            }
        });
        valueAnimator.start();
    }

監聽器三個
image.png


        //監聽1
        valueAnimator.addPauseListener(new Animator.AnimatorPauseListener() {
            @Override
            public void onAnimationPause(Animator animation) {
                //暫停
            }

            @Override
            public void onAnimationResume(Animator animation) {
                //運行
            }
        });

        //監聽2
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                //開始
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //結束
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                //取消
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                //回圈一次
            }
        });

        //監聽3
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //數值更新
            }
        });

移除監聽器
當移除監聽器時,正在執行的影片不會受到影響,但是之后再執行影片,影片的監聽效果將不會再呈現,

/** 
 * 移除AnimatorUpdateListener 
 */  
void removeUpdateListener(AnimatorUpdateListener listener);  
void removeAllUpdateListeners();  

 /** 
  * 移除AnimatorListener 
  */  
void removeListener(AnimatorListener listener);  
void removeAllListeners();

不常用函式

/**
 * 延時多久時間開始,單位是毫秒
 */
public void setStartDelay(long startDelay)
    
/**
 * 完全克隆一個ValueAnimator實體,包括它所有的設定以及所有對監聽器代碼的處理
 */
public ValueAnimator clone()

常用函式

/**
 * 設定影片時長,單位是毫秒
 */
ValueAnimator setDuration(long duration)
    
/**
 * 獲取ValueAnimator在運動時,當前運動點的值
 */
Object getAnimatedValue();

/**
 * 開始影片
 */
void start()
    
/**
 * 設定回圈次數,設定為INFINITE表示無限回圈
 */
void setRepeatCount(int value)
    
/**
 * 設定回圈模式
 * value取值有RESTART,REVERSE,
 */
void setRepeatMode(int value)
    
/**
 * 取消影片
 */
void cancel()

效果:

屬性影片.gif

二、自定義插值器

1.插值器的理解

首先看看自動自定義的插值器
勻速插值器:
看看繼承關系:LinearInterpolator---繼承--->BaseInterpolator---繼承--->Interpolator---實作-->TimeInterpolator
最后看看TimeInterpolator都寫了啥:
只定義了一個getInterpolation(float input)方法,

package android.animation;

/**
 * A time interpolator defines the rate of change of an animation. This allows animations
 * to have non-linear motion, such as acceleration and deceleration.
 */
public interface TimeInterpolator {

    /**
     * Maps a value representing the elapsed fraction of an animation to a value that represents
     * the interpolated fraction. This interpolated value is then multiplied by the change in
     * value of an animation to derive the animated value at the current elapsed animation time.
     *
     * @param input A value between 0 and 1.0 indicating our current point
     *        in the animation where 0 represents the start and 1.0 represents
     *        the end
     * @return The interpolation value. This value can be more than 1.0 for
     *         interpolators which overshoot their targets, or less than 0 for
     *         interpolators that undershoot their targets.
     */
    float getInterpolation(float input);
}

LinearInterpolator的定義


public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input; //數值進度與時間同步
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}

AccelerateInterpolator開始慢,后面一直加速插值器,也叫冪函式插值器,核心方法

 public float getInterpolation(float input) {
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            //回傳的是時間的次冪數,比如 input=3,mDoubleFactor=2,
            //那么回傳的就是,3的2次方,就是9
            //所以會按照幾何倍增,這是一個冪函式
            return (float)Math.pow(input, mDoubleFactor); 
        }
    }

所有的速度都離不開這個方法:getInterpolation

而最為關鍵的就是input這個數字,以下是經典解釋:

input引數代表了當前影片的進度,而回傳值則代表了當前影片的數值進度,

上面的勻速,回傳的就是時間的值,所以,影片進度和影片的數值持平,
冪函式的時候,隨著影片進度的增加,影片的數值進度也就越來越大,從而一直加速,

input的取值范圍是0~1之間,回傳值可以超過1,也可以小于0,超過1表示已經超過目標位置,小于0表示遠離初始位置,

簡單的公式就是

y= -> x

y代表回傳的值,也就是影片需要的數值進度,x代表時間進度,->則是通過一些數學手段,來得到想要的y值,

  • 當一些影片定義這些插值器的時候,回傳的數值進度越大,速度越快,比如你在勻速運動的時候,時間進度是0.5s,數值進度也是0.5,那就是勻速運動,

2.定義一個簡單的插值器

我們用數學中的定義來做一個插值器,
y=1-x
把進度反過來,當進度傳入0的時候,數值進度已經在目標位置了,當傳入1時,數值則在剛開始的位置,

  class FiveInterpolator implements TimeInterpolator {

        @Override
        public float getInterpolation(float input) {
            return 1-input;
        }
    }

valueAnimator.setInterpolator(``new ``FiveInterpolator())``;
一個簡單的自定義插值器就完成了,

三、Evaluator

  • Evaluator是數值轉換器,就是將數值進度轉化為具體的數值,
  • 就是0~400的數值變換,當數值進度是50%的時候,那通過Evaluator來轉換,就變成了200
  • oflnt()函 數對應 Evauator 類名為 IntEvauaor ,而 ofFloat()函式對應的 Evauator 類名為 FloatEvaluator

自定義數值轉換器:

 	//自定義數值轉換器
    class MyFloatEvaluator implements TypeEvaluator<Float>{

        /**
         * @param fraction 代表數值進度的值,就是上面getInterpolation()的回傳值
         * @param startValue  代表ofFloat(Float startValue,Float endValue)
         * @param endValue
         * */
        @Override
        public Float evaluate(float fraction, Float startValue, Float endValue) {
            //初始值
            Float startFloat=startValue;

            //當前值=初始值+總值*進度
            Float inputValue=https://www.cnblogs.com/lanjiabin/p/startFloat+(endValue-startFloat)*fraction;
            return inputValue;
        }
    }

使用:

valueAnimator.setEvaluator(new MyFloatEvaluator());

所以可以通過插值器和數值轉化器來改變控制元件的數值變化

valueAnimator.setInterpolator(new FiveInterpolator());
valueAnimator.setEvaluator(new MyFloatEvaluator());

四、ArgbEvaluator

ArgbEvaluator可以把顏色轉換過渡,
具體實作:

 //顏色的數值變換
    public void doColorAnimation(){
        ValueAnimator valueAnimator=ValueAnimator.ofInt(0xffffff00,0xff0000ff);
        valueAnimator.setEvaluator(new ArgbEvaluator());
        valueAnimator.setDuration(3000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int curValue=https://www.cnblogs.com/lanjiabin/p/(int)animation.getAnimatedValue();
                valueTV.setBackgroundColor(curValue);
            }
        });
        valueAnimator.start();
    }

效果:

顏色變換.gif

顏色必須包含ARGB四個值,
image.png

五、ValueAnimation-ofObject

首先看看這個方法是如何傳值的,

public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setObjectValues(values);
        anim.setEvaluator(evaluator);
        return anim;
    }

TypeEvaluator evaluator需要傳入自定義的數值轉換器
Object... values 可變長引數

實體
實作一個字母從A到Z的程序

public void doObjectValue() {
        ValueAnimator valueAnimator = ValueAnimator.ofObject(new CharInterpolator(), new Character('A'), new Character('Z'));
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                char str = (char) animation.getAnimatedValue();
                valueTV.setText(String.valueOf(str));
            }
        });
        valueAnimator.setDuration(7000);
        valueAnimator.setInterpolator(new AccelerateInterpolator());
        valueAnimator.start();
    }

    class CharInterpolator implements TypeEvaluator<Character> {

        @Override
        public Character evaluate(float fraction, Character startValue, Character endValue) {
            int startInt = (int) startValue;  //ASCII轉換   A代表56 以此遞增
            int endInt = (int) endValue;
            int curInt = (int) (startInt + fraction * (endInt - startInt));
            char result = (char) curInt;
            return result;
        }
    }

效果:

A-Z的變換.gif

六、ObjectAnimator

ObjeceAnimation--繼承--->ValueAnimation
與控制元件之間相關聯,從監聽影片中解放出來,
先看看這個方法:

ObjectAnimator ofFloat(Object target, String propertyName, float... values)

具體使用

  public void doObjectAnimationByAlpha(){
        ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(valueTV,"alpha",1,0,1);
        objectAnimator.setDuration(6000);
        objectAnimator.start();
    }

Object target要控制的控制元件
String propertyName要改變的影片效果
float... values傳入的具體變化值
具體效果就是跟視圖影片中設定的影片是一樣的效果,透明度從1到0再到1.
“alpha”中,是對應view中的setAlpha()方法,后面的可變成引數就是可以傳入具體是變換數值,
看看view中有多少個set函式:

透明度:alpha

setAlpha(@FloatRange(from=0.0, to=1.0) float alpha)  //透明度

旋轉角度:rotation,rotationX,rotationY

setRotation(float rotation) //圍繞Z軸旋轉,Z軸指的是垂直螢屏的方向
setRotationX(float rotationX)  //圍繞X軸旋轉
setRotationY(float rotationY)  //圍繞Y軸旋轉

平移:translationX,translationY

setTranslationX(float translationX)   //X軸螢屏,右為正方向,當前控制元件為原點
setTranslationY(float translationY)

縮放:scaleX,scaleY

setScaleX(float scaleX) //X軸縮放
setScaleY(float scaleY)

看看旋轉是三個效果:

 public void doObjectAnimationByAlpha(){
        ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(valueTV,"rotationY",360);
        objectAnimator.setDuration(6000);
        objectAnimator.start();
    }

Z軸:

Z軸旋轉.gif

X軸:

X軸旋轉.gif

Y軸:

Y軸旋轉.gif

七、自定義ObjectAnimator

因為ObjectAnimator是通過set來反射實作的,所以自己也可以通過這樣的操作來實作自己view的set函式,從而實作簡單的影片效果,

1.自定義view的set函式

FallingBallImageView.java

public class FallingBallImageView extends ImageView {
    public FallingBallImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public void setFallingPos(Point pos){
        layout(pos.x,pos.y,pos.x+getWidth(),pos.y+getHeight());
    }

}

布局使用

<com.lanjiabin.systemtest.anim.FallingBallImageView
                android:id="@+id/imageBall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="30dp"
                android:background="@drawable/shape"
                android:layout_marginBottom="25dp" />

set函式的名字是setFallingPos,所以在傳遞反射函式名字的時候,應該是fallingPos或者FallingPos,必須是這兩個名字中其中一個的格式,否則就不會正確反射,引數型別是Point,所以使用函式是ofObject()

2.自定義Evaluator

 class DivEvaluator implements TypeEvaluator<Point> {
        Point point = new Point();

        @Override
        public Point evaluate(float fraction, Point startValue, Point endValue) {
            point.x = (int) (startValue.x + (endValue.x - startValue.x) * fraction);
            if (fraction * 2 <= 1) {
                point.y = (int) (startValue.y + (endValue.y - startValue.y) * fraction);
            } else {
                point.y = endValue.y;
            }
            return point;
        }
    }

3.實作最終反射呼叫

  public void doObjectAnimationByDiv() {
        ObjectAnimator objectAnimator=ObjectAnimator
                .ofObject(
                        ballImageView,  //自定義view的小球
                        "FallingPos",   //反射名字,FallingPos或者fallingPos都可以
                        new DivEvaluator(), //自定義轉換器
                        new Point(0,0),     //起始坐標
                        new Point(300,300)); //目標坐標
        objectAnimator.setDuration(4000);   //影片時長
        objectAnimator.start();
    }

4.效果

自定義ObjectAnimation.gif

5.get函式

當我們在上述函式的時候,ofObject()傳的都是可變長的引數,也就是兩個引數以上,當我們只傳遞一個引數的時候,這個引數只是目標引數,沒有初始引數,系統就會默認呼叫系統自帶的get方法,來獲得初始值,當沒有這個get方法的時候,就會報錯,以至于崩潰,
所以想傳遞一個引數,就需要自定義get()方法,回傳的,就是初始值,對應名字也和set的名字類似,
setFallingPos(Point pos)的名字就是getFallingPos(Point pos)

在自定義view中加入get方法:回傳控制元件的初始Point

 public Point getFallingPos() {
        int[] location = new int[2];
        this.getLocationOnScreen(location);
        return new Point(location[0], location[1]);
    }

八、AnimatorSet

1.AnimatorSet理解和使用

AnimatorSet組合影片,對ValueAnimation和ObjectAnimation都有一樣的效果,
有兩個播放方法:只管播放的時間,不管影片個體是如何操作的,不管影片的執行時間,回圈次數等,
playSequentially()
是順序播放,當前一個影片播放完畢以后,才會執行下一個影片,當前一個影片是無限回圈時,后一個影片也就無法播放,有兩個構造方法,

playSequentially(Animator... items)
playSequentially(List<Animator> items)

playTogether()
是一起播放,同一個時間內,在串列中所有影片同一時間啟動,

playTogether(Animator... items)
playTogether(Collection<Animator> items)

具體實體,有一個縮放影片和位移影片,分別實作同時播放和順序播放,

 public void doAnimationSet() {
        //縮放
        ObjectAnimator objectAnimatorScaleY = ObjectAnimator.ofFloat(ballImageView, "scaleY", 0.0f, 1.6f, 1.0f);

        //平移
        ObjectAnimator objectAnimatorTranslationX = ObjectAnimator.ofFloat(ballImageView, "translationX", 400);

        //組合影片
        AnimatorSet animator = new AnimatorSet();

        //每個影片的播放時間
        animator.setDuration(3000);

        //順序播放
        animator.playSequentially(objectAnimatorScaleY, objectAnimatorTranslationX);

        //一起播放
        animator.playTogether(objectAnimatorScaleY, objectAnimatorTranslationX);

        animator.start();
    }

同時播放:影片效果同時體現出來,縮放和位移
組合影片-同時播放.gif

順序播放:先縮放完畢再位移
組合影片-順序播放.gif

2.AnimatorSet.Builder

  		//組合影片
        AnimatorSet animator = new AnimatorSet();

        //目標影片
        AnimatorSet.Builder builder=animator.play(objectAnimatorScaleY);

        //執行目標影片后再執行該影片
        builder.after(objectAnimatorScaleY);

        //執行該影片后再執行目標影片
        builder.before(objectAnimatorScaleY);

        //和目標影片一起播放
        builder.with(objectAnimatorScaleY);

        //延遲時間執行目標影片
        builder.after(3000);


		//串行方式
        AnimatorSet animator = new AnimatorSet();
        AnimatorSet.Builder builder=animator
        	.play(objectAnimatorScaleY)
            .after(objectAnimatorScaleY)
            .before(objectAnimatorScaleY);


		//如果AnimatorSet設定了影片時長,回圈次數等,都以AnimatorSet為準,單個設定不起作用,
        //每個影片的播放時間
        animator.setDuration(3000);
  		//所有的影片都集中于這個控制元件上,其它的不起作用
        animator.setTarget(ballImageView);

九、實體-衛星選單

1.實作原理

實作一個放射衛星的效果,點擊一下,放射出選單,再點擊一下,識訓選單,
原理就是,將所有的選單重疊在一起,點擊最上面的選單,按照不同的角度,實作位移,縮放,透明度的效果,將下面的選單都位移出去,看看位移的計算方式,每個選單,與主選單都形成了直角形式,水平X軸的位移和Y軸的水平位移都可以計算出來, 就是從主選單,位移到不同位置的X軸和Y軸,
計算公式.png

2.布局

布局非常簡單,全部控制元件疊加在一起,而且子選單的屬性全部一致,省略了一些重復的空間,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="20dp">

        <!-- Shadow 代表陰影,對陰影的一些處理-->
        <Button
            android:id="@+id/mainBtn"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_gravity="center_vertical|right"
            android:layout_marginRight="40dp"
            android:background="@drawable/menu_main"
            android:outlineAmbientShadowColor="@android:color/transparent"
            android:outlineSpotShadowColor="@android:color/transparent"
            android:shadowColor="@android:color/transparent" />

        <Button
            android:id="@+id/rockBtn"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_gravity="center_vertical|right"
            android:layout_marginRight="20dp"
            android:background="@drawable/menu_rock"
            android:outlineAmbientShadowColor="@android:color/transparent"
            android:outlineSpotShadowColor="@android:color/transparent"
            android:shadowColor="@android:color/transparent"
            android:visibility="gone" />
                
            <!-- 以下省略六個子按鈕選單 -->    
    </FrameLayout>


</LinearLayout>

3.java代碼

核心思想就是,添加要控制的子選單,開啟影片方法,關閉影片方法,


public class ExampleActivity extends BaseActivity {

    private boolean mIsMenuOpen = false;
    private Button mMainBtn, mRockBtn, mAirBtn, mTrainBtn, mCarBtn, mMotorbikeBtn, mBicycleBtn, mWalkBtn;
    List<Button> mBtnArray;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();
        OnClick();
    }

    public void initView() {
        setContentView(R.layout.activity_example);
        mMainBtn = findViewById(R.id.mainBtn);

        mRockBtn = findViewById(R.id.rockBtn);
        mAirBtn = findViewById(R.id.airBtn);
        mTrainBtn = findViewById(R.id.trainBtn);
        mCarBtn = findViewById(R.id.carBtn);
        mMotorbikeBtn = findViewById(R.id.motorbikeBtn);
        mBicycleBtn = findViewById(R.id.bicycleBtn);
        mWalkBtn = findViewById(R.id.walkBtn);

        //添加子選單
        mBtnArray = new ArrayList<Button>();
        mBtnArray.add(mRockBtn);
        mBtnArray.add(mAirBtn);
        mBtnArray.add(mTrainBtn);
        mBtnArray.add(mCarBtn);
        mBtnArray.add(mMotorbikeBtn);
        mBtnArray.add(mBicycleBtn);
        mBtnArray.add(mWalkBtn);
    }

    public void OnClick() {
        mMainBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchAnimation();
            }
        });

        mRockBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(ExampleActivity.this, "你選擇了火箭出行!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    //開關
    public void switchAnimation() {
        if (!mIsMenuOpen) {
            mIsMenuOpen = true;
            for (int i = 0; i < mBtnArray.size(); i++) {
                doAnimationOpen(mBtnArray.get(i), i, mBtnArray.size(), 500);
            }
        } else {
            mIsMenuOpen = false;
            for (int i = 0; i < mBtnArray.size(); i++) {
                doAnimationClose(mBtnArray.get(i), i, mBtnArray.size(), 500);
            }
        }
    }

    /**
     * 開啟影片/展開選單
     * @param view   要控制的控制元件/子選單
     * @param index  要控制控制元件的順序
     * @param total  子選單的總數
     * @param radius 主選單到子選單的距離/半徑
     * */
    private void doAnimationOpen(View view, int index, int total, int radius) {

        //顯示選單
        if (view.getVisibility() != View.VISIBLE) {
            view.setVisibility(View.VISIBLE);
        }

        //計算每個選單的角度,toRadians()將度數轉換為弧度
        //七個子選單,有六個夾角角,180/(7-1)*2  2代表第二個夾角
        double degree = Math.toRadians(180) / (total - 1) * index;

        //X軸位移
        int translationX = -(int) (radius * Math.sin(degree));

        //Y軸位移
        int translationY = -(int) (radius * Math.cos(degree));
        AnimatorSet animatorSet = new AnimatorSet();

        //影片合集
        animatorSet.playTogether(

                //從原來控制元件的位置往X軸移動多少
                ObjectAnimator.ofFloat(view, "translationX", 0, translationX),

                //從原來控制元件的位置往Y軸移動多少
                ObjectAnimator.ofFloat(view, "translationY", 0, translationY),

                //X軸縮放
                ObjectAnimator.ofFloat(view, "scaleX", 0.01f, 1f),

                //Y軸縮放
                ObjectAnimator.ofFloat(view, "scaleY", 0.01f, 1.0f),

                //透明度
                ObjectAnimator.ofFloat(view, "alpha", 0.01f, 1.0f)
        );
        animatorSet.setDuration(500);
        animatorSet.start();
    }

    //關閉選單/影片
    private void doAnimationClose(View view, int index, int total, int radius) {
        if (view.getVisibility() != View.VISIBLE) {
            view.setVisibility(View.VISIBLE);
        }
        double degree = Math.toRadians(180) / (total - 1) * index;
        int translationX = -(int) (radius * Math.sin(degree));
        int translationY = -(int) (radius * Math.cos(degree));
        AnimatorSet animatorSet = new AnimatorSet();

        animatorSet.playTogether(
                ObjectAnimator.ofFloat(view, "translationX", translationX, 0),
                ObjectAnimator.ofFloat(view, "translationY", translationY, 0),
                ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 0.01f),
                ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 0.01f),
                ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0.01f)
        );
        animatorSet.setDuration(500);
        animatorSet.start();
    }
}

3.效果

衛星選單.gif

十、XML實作Animator

1.animator

在animator下建立animator.xml

image.png

xml代碼:

<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:valueFrom="0"
    android:valueTo="300"
    android:valueType="intType" />

java代碼使用

  ValueAnimator valueAnimator=(ValueAnimator)AnimatorInflater.loadAnimator(
                                ExampleActivity.this,
                                R.animator.animator);

                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        int offset=(int)animation.getAnimatedValue();
                        mRockBtn.layout(offset,offset,mRockBtn.getWidth()+offset,mRockBtn.getHeight()+offset);
                    }
                });
                valueAnimator.start();

2.ObjectAnimator

object_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"  //時間
    android:interpolator="@android:anim/accelerate_interpolator"  //插值器
    android:propertyName="string"  //要映射的名字
    android:repeatCount="11"      //回圈次數
    android:repeatMode="restart"  //回圈模式
    android:startOffset="777"     
    android:valueFrom="99"  //開始
    android:valueTo="199"   //目標
    android:valueType="intType"  //資料型別
    />

java代碼使用

  ObjectAnimator animator=(ObjectAnimator)AnimatorInflater.loadAnimator(
                        ExampleActivity.this,
                        R.animator.object_animator);
                animator.setTarget(mAirBtn);
                animator.start();

十一、后語

包括其它的知識點,都只能說一些基礎的內容,很多方法和拓展知識都沒有說道,需要自己去探索,多閱讀SDK原始碼,屬性影片,有一些高級的內容,后續會持續拓展,

編程中我們會遇到多少挫折?表放棄,沙漠盡頭必是綠洲,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/5570.html

標籤:Android

上一篇:Android EXCEL 決議 xls 和 xlsx,方法其實很簡單

下一篇:Android 自定義View—清爽小巧靈活的多節點進度條

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more