主頁 > 移動端開發 > 天啦嚕!原來Android屬性影片也不過如此

天啦嚕!原來Android屬性影片也不過如此

2021-03-03 16:50:00 移動端開發

前兩篇《天啦嚕!原來Android補間影片可以這么玩》和《天啦嚕!原來Android幀影片這么簡單》重點講述了Android開發程序中補間影片和幀影片知識點,本篇文章我們重點總結一下屬性影片的使用和原理,

Android影片系列:

  • 《天啦嚕!原來Android補間影片可以這么玩》
  • 《天啦嚕!原來Android幀影片這么簡單》
  • 《天啦嚕!原來Android屬性影片也不過如此》

什么是屬性影片

在一段時間內通過修改物件的屬性而形成的影片叫屬性影片(Property Animation),Google官方在Android 3.0添加Property Animation,屬性影片的主要是修改物件的屬性,如 View 的背景顏色、透明值、位置等,

屬性影片和補間影片的區別

有同學可能會問不是已經有補間影片嗎,為什么要引入屬性影片?換句話說,Property Animation 到底能干哪些 Tween Animation 不能干的活呢?

Tween Animation 存在的問題:

  1. Tween Animation 只能作用于 View,不能作用于普通 Object 的屬性,
  2. Tween Animation 只能改變 View 的一部分屬性,Tween Animation 只支持修改 View 的這幾個方面:Alpha、Scale、Translate、Rotate 和這些的組合,一旦想要改變的 View 的屬性不在這個范圍內,Tween Animation 就無能為力了,如 View 的 BackgroundColor,
  3. Tween Animation 只能改變 View 的“表面”位置,不能改變 View 的實際位置,

屬性影片相關類

屬性影片涉及的類主要有:

  1. Animator,所有 Animator 的父類,主要用于定義通用的介面,
  2. AnimatorSet,主要用于組合多個屬性影片,
  3. ValueAnimator,屬性影片的一種,主要用于根據起始值和終止值產生影片,只負責產生在起始值和終止值之間的值,
    不負責更新界面,需要用戶自己實作更新界面的邏輯,
  4. ObjectAnimator,屬性影片的一種,主要用于根據起始值和終止值產生影片,并將影片產生的值設定在目標物件上,
  5. TimeAnimator,提供了一個簡單的回呼機制,通過 TimeAnimator.TimeListener,在影片的每一幀處通知你,這個影片器沒有時間,插值或是物件值設定,回呼監聽器為每一幀影片接受資訊,包括總運行時間和從前一幀到現在的運行時間,

繼承結構如下:

屬性影片繼承結構圖

ValueAnimator和ObjectAnimator主要區別

該類作為ValueAnimator的子類不僅繼承了ValueAnimator的所有方法和特性,并且還封裝很多實用的方法,方便開發人員快速實作影片,同時,由于屬性值會自動更新,使用ObjectAnimator實作影片不需要像ValueAnimator那樣必須實作 ValueAnimator.AnimatorUpdateListener ,因此實作任意物件的影片顯示就更加容易了,我們在大部分的開發作業中,都會使用ObjectAnimator而非ValueAnimator實作我們所需的影片效果,

屬性影片實作形式

屬性影片的實作形式有兩種:xml創建和code實作,其中xml創建的xml影片檔案要放在res/animator目錄下,注意此處和補間影片(Tween Animation)存放位置不同,

通常情況下屬性影片一般建議通過代碼進行實作,因為他更靈活,尤其是在自定義View中常常有屬性影片的身影,當然也需要根據實際場景自行選擇,下邊就通過這兩種形式來總結一下屬性影片幾個類的使用,

ValueAnimator

ValueAnimator是Property Animation系統的核心類,它包含了配置Property Animation屬性的大部分方法,那要實作一個Property Animation,都需要直接或間接使用ValueAnimator類,

一般使用ValueAnimator實作影片分為以下幾個步驟:

  1. 呼叫ValueAnimation類中的ofInt(int…values)、ofFloat(String propertyName,float…values)等靜態方法實體化ValueAnimator物件;
  2. 呼叫addUpdateListener(AnimatorUpdateListener mListener)方法為ValueAnimator物件設定屬性變化的監聽器,并在AnimatorUpdateListener 中的實作方法為目標物件的屬性設定計算好的屬性值,
  3. 創建自定義的插值器(Interpolator),呼叫setInterpolator(TimeInterpolator value)為ValueAniamtor設定自定義的Interpolator;(可選,不設定默認為預設值)
  4. 創建自定義的估值器(TypeEvaluator),呼叫setEvaluator(TypeEvaluator value)為ValueAnimator設定自定義的TypeEvaluator;(可選,不設定默認為預設值)
  5. 設定影片的持續時間、是否重復及重復次數等屬性;
  6. 為ValueAnimator設定目標物件并開始執行影片,

需要注意目標物件的需要被設定的屬性必須擁有get\set方法,格式類似 set(),

通過XML創建

語法

<animator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="int"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:valueType=["intType" | "floatType"]
    android:valueFrom="float | int | color"
    android:valueTo="float | int | color"
    android:startOffset="int"
    android:repeatCount="int"
    android:repeatMode=["repeat" | "reverse"]
    />

ValueAnimator屬性詳解

示例

//1. 創建 value_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1800"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:valueType="floatType"
    android:valueFrom="-100"
    android:valueTo="800"
    android:startOffset="0"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    />
    
//2. 在代碼中使用 value_animator
ValueAnimator mValueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.value_animator);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        mTarget.setY((Float) animation.getAnimatedValue());
    }
});
mValueAnimator.start();

通過代碼實作

語法

ValueAnimator valueAnimator = ValueAnimator.ofFloat(float... values);
valueAnimator.setDuration(long duration);
valueAnimator.setInterpolator(TimeInterpolator value);
valueAnimator.addUpdateListener(AnimatorUpdateListener listener);
…
valueAnimator.start();

示例

ValueAnimator mValueAnimator = ValueAnimator.ofFloat(0, 800);
mValueAnimator.setDuration(1800);
mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
mValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        mTarget.setY((Float) animation.getAnimatedValue());
    }
});
mValueAnimator.start();

ObjectAnimator

要影片顯示 View 物件的某個屬性,比如顏色或旋轉值,我們所有要做的事情就是創建一個 Property animation,并設定對應的 View 屬性,那接下來我們就用ObjectAnimator類來分別實作View的透明度漸變、收縮、移動和旋轉等影片效果,那在此之前我們也來總結下使用ObjectAnimator實作影片的幾個步驟,如下:

  1. 通過呼叫ofFloat()、ofInt()等方法創建ObjectAnimator物件,并設定目標物件、需要改變的目標屬性名、初始值和結束值;
  2. 設定影片的持續時間、是否重復及重復次數等屬性;
  3. 啟動影片,

常用的幾個屬性值解釋:

  • translationX 和 translationY:這兩個屬性控制著 View 的螢屏位置坐標變化量,以 layout 容器的左上角為坐標原點;
  • rotation、rotationX 和 rotationY:這三個屬性控制著 2D 旋轉角度(rotation屬性)和圍繞某樞軸點的 3D 旋轉角度;
  • scaleX、scaleY:這兩個屬性控制著 View 圍繞某樞軸點的 2D 縮放比例;
  • pivotX 和 pivotY: 這兩個屬性控制著樞軸點的位置,前述的旋轉和縮放都是以此點為中心展開的,預設的樞軸點是 View 物件的中心點;
  • x 和 y:這是指 View 在容器內的最終位置,等于 View 左上角相對于容器的坐標加上 translationX 和 translationY 后的值;
  • alpha:表示 View 的 alpha 透明度,預設值為 1 (不透明),為 0 則表示完全透明(看不見);

通過XML創建

語法

<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="int"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:propertyName="string"
    android:valueType=["intType" | "floatType"]
    android:valueFrom="float | int | color"
    android:valueTo="float | int | color"
    android:startOffset="int"
    android:repeatCount="int"
    android:repeatMode=["repeat" | "reverse"]
    />

ObjectAnimator屬性詳解

示例

//1. 創建 object_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1800"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:propertyName="Y"
    android:valueType="floatType"
    android:valueFrom="0"
    android:valueTo="800"
    android:startOffset="0"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    />
    
//2. 在代碼中使用 object_animator
ObjectAnimator mObjectAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.object_animator);
mObjectAnimator.setTarget(mTarget);
mObjectAnimator.start();

通過代碼實作

語法

ObjectAnimator objectAnimator = ObjectAnimator.ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values);
objectAnimator.setDuration(long duration);
objectAnimator.setInterpolator(TimeInterpolator value);
…
objectAnimator.start();

示例

ObjectAnimator mObjectAnimator = ObjectAnimator.ofFloat(mTarget, "y", 0, 800);
mObjectAnimator.setDuration(1800);
mObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
mObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
mObjectAnimator.start();

AnimatorSet

通過XML創建

語法

<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering=["together" | "sequentially"]>

    <objectAnimator
        android:propertyName="string"
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <animator
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <set>
        ...
    </set>
</set>

AnimatorSet屬性詳解

示例

//1. 創建 animator_set.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together"
    >
    <objectAnimator
        android:duration="@integer/integer_one_thousand_and_eight_hundred"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="Y"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="800"
        android:startOffset="0"
        android:repeatCount="infinite"
        android:repeatMode="reverse"
        />
    <objectAnimator
        android:duration="@integer/integer_one_thousand_and_eight_hundred"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="ScaleX"
        android:valueType="floatType"
        android:valueFrom="1"
        android:valueTo="2"
        android:startOffset="0"
        android:repeatCount="infinite"
        android:repeatMode="reverse"
        />
    <objectAnimator
        android:duration="@integer/integer_one_thousand_and_eight_hundred"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="ScaleY"
        android:valueType="floatType"
        android:valueFrom="1"
        android:valueTo="2"
        android:startOffset="0"
        android:repeatCount="infinite"
        android:repeatMode="reverse"
        />
</set>

//2. 在代碼中使用 animator_set
AnimatorSet mAnimatorSet = (AnimatorSet)AnimatorInflater.loadAnimator(this, R.animator.animator_set);
mAnimatorSet.setTarget(mTarget);
mAnimatorSet.start();

通過代碼實作

語法

AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(Animator... items);
animatorSet.playSequentially(Animator... items);
//非必須
animatorSet.setTarget(mTarget);
…
animatorSet.start();

示例

ObjectAnimator translateYObjectAnimator = ObjectAnimator.ofFloat(mTarget, "y", 0, 800);
translateYObjectAnimator.setDuration(1800);
translateYObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
translateYObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
translateYObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
ObjectAnimator scaleXObjectAnimator = ObjectAnimator.ofFloat(mTarget, "scaleX", 1, 2);
scaleXObjectAnimator.setDuration(1800);
scaleXObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
scaleXObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
scaleXObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
ObjectAnimator scaleYObjectAnimator = ObjectAnimator.ofFloat(mTarget, "scaleY", 1, 2);
scaleYObjectAnimator.setDuration(1800);
scaleYObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
scaleYObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
scaleYObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(translateYObjectAnimator, scaleXObjectAnimator, scaleYObjectAnimator);
mAnimatorSet.playSequentially();
//非必須
//        mAnimatorSet.setTarget(mTarget);
mAnimatorSet.start();

監聽屬性影片

Property Animation 中一共有三種監聽事件:

  • AnimatorListener;
  • AnimatorPauseListener;
  • AnimatorUpdateListener;

AnimatorListener

AnimatorListener 介面主要用于監聽 Property Animation 的開始、結束、取消、重復狀態,需要實作的方法分別是:

@Override
public void onAnimationStart(Animator animation) {}

@Override
public void onAnimationEnd(Animator animation) {}

@Override
public void onAnimationCancel(Animator animation) {}

@Override
public void onAnimationRepeat(Animator animation) {}

AnimatorPauseListener

AnimatorPauseListener 主要用于監聽 Property Animation 的暫停、恢復狀態,需要實作的方法分別是:

@Override
public void onAnimationPause(Animator animation) {}

@Override
public void onAnimationResume(Animator animation) {}

AnimatorUpdateListener

AnimatorUpdateListener 是 ValueAnimator 及其子類特有的介面,主要用于監聽影片中值的變化,用于手動更新界面,需要實作的方法是:

@Override
public void onAnimationUpdate(ValueAnimator animation) {}

屬性影片作業原理

當 ValueAnimator 呼叫 start 方法之后,ValueAnimator 會根據 Property Animation 當前運行時間與總的影片持續時間計算出一個時間消耗百分數(The elapsed fraction),緊接著,ValueAnimator 將這個時間消耗百分數交給當前 ValueAnimator 的插值器(Interpolator),不同的 Interpolator 會根據不同的演算法將這個時間消耗百分數轉換成插值百分數(The interpolated fraction),緊接著,ValueAnimator 會將這個插值百分數交給當前 ValueAnimator 的估值器(TypeEvaluator),不同的 TypeEvaluator 會根據不同的演算法將這個插值百分數轉換最終的影片值(The final value),

拿AccelerateDecelerateInterpolator插值器舉例:

public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    public AccelerateDecelerateInterpolator() {
    }

    @SuppressWarnings({"UnusedDeclaration"})
    public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
    }

    /**
     * param input (The elapsed fraction)
     * return (The interpolated fraction)
     */
    public float getInterpolation(float input) {
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
    }

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

AccelerateDecelerateInterpolator屬性影片作業原理

上面這個屬性影片的 Duration 為 40ms,Intepolator 為 AccelerateDecelerateInterpolator,Distance 為 40,

在 t = 10ms 時,The elapsed fraction 為 0.25 = 10/40,The interpolated fraction = (float)(Math.cos((0.25 + 1) * Math.PI) / 2.0f) + 0.5f = 0.14644662,The final value 為 5.8578648 = (40 - 0) * 0.14644662,

自定義插值器

自定義插值器要實作 Interpolator 介面,上篇文章已經有所說明,不做過多闡述,

public class DecelerateAccelerateInterpolator implements Interpolator {

    @Override
    public float getInterpolation(float input) {
        return (float) ((Math.tan(Math.PI/2 * input - Math.PI/4) + 1)/2);
    }
}

自定義估值器

自定義估值器,只要實作 TypeEvaluator 介面,并實作其中定義的 evaluate 方法即可:

public class CustomTypeEvaluator implements TypeEvaluator {

    /**
     * param fraction 插值器最終值
     * param startValue 屬性開始值
     * param endValue 屬性結束值
     */
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return 200 + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

ViewPropertyAnimator 使用簡介

ViewPropertyAnimator、ObjectAnimator、ValueAnimator 這三種 Animator,它們其實是一種遞進的關系:從左到右依次變得更加難用,也更加靈活,

它們的性能是一樣的,因為 ViewPropertyAnimator 和 ObjectAnimator 的內部實作其實都是 ValueAnimator,ObjectAnimator 更是本來就是 ValueAnimator 的子類,它們三個的性能并沒有差別,

它們的差別只是使用的便捷性以及功能的靈活性,所以在實際使用時候的選擇,只要遵循一個原則就行:盡量用簡單的,能用 View.animate() 實作就不用 ObjectAnimator,能用 ObjectAnimator 就不用 ValueAnimator,

當需要同時更改 View 的多個屬性的時候,一般有三種方法:

  1. ObjectAnimator + AnimatorSet;
  2. PropertyValuesHolder + ObjectAnimator;
  3. ViewPropertyAnimator;

接下來,分別用三種方法分別實作同一種效果:View 的 Y 值從當前位置增到 400,Alpha 值 從 1.0f 變成 0.1f,

ObjectAnimator + AnimatorSet

ObjectAnimator alphaObjectAnimator = ObjectAnimator.ofFloat(mTarget, "alpha", 1.0f, 0.1f);
ObjectAnimator yObjectAnimator = ObjectAnimator.ofFloat(mTarget, "y", 400f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(alphaObjectAnimator, yObjectAnimator);
animatorSet.start();

PropertyValuesHolder + ObjectAnimator

PropertyValuesHolder alphaPropertyValuesHolder = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.1f);
PropertyValuesHolder yPropertyValuesHolder = PropertyValuesHolder.ofFloat("y", 400f);
ObjectAnimator.ofPropertyValuesHolder(mTarget, alphaPropertyValuesHolder, yPropertyValuesHolder).start();

ViewPropertyAnimator

ViewPropertyAnimator viewPropertyAnimator = mTarget.animate();
viewPropertyAnimator.alpha(0.1f);
viewPropertyAnimator.y(400f);

//也可以寫成一句:
mTarget.animate().alpha(0.1f).y(400f);

PropertyValuesHolder

細心的同學可能會注意到,ValueAnimator、ObjectAnimator除了這些創建Animator實體的方法以外,都還有一個方法:

/**
 * valueAnimator的
 */
public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) 
/**
 * ObjectAnimator的
 */
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)

PropertyValuesHolder這個類的意義就是,它其中保存了影片程序中所需要操作的屬性和對應的值,我們通過ofFloat(Object target, String propertyName, float… values)構造的影片,ofFloat()的內部實作其實就是將傳進來的引數封裝成PropertyValuesHolder實體來保存影片狀態,在封裝成PropertyValuesHolder實體以后,后期的各種操作也是以PropertyValuesHolder為主的,

使用舉例:

PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder);
animator.setDuration(3000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();

參考

  • https://developer.android.com/reference/android/animation/Animator
  • https://carsonho.blog.csdn.net/article/details/72909894
  • https://blog.csdn.net/harvic880925/article/details/50752838
  • https://juejin.cn/post/6844903798687678478#heading-34

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

標籤:其他

上一篇:Andorid 自定義View 仿大眾點評 星星評分控制元件

下一篇:Android點擊button彈出ProgressDialog,回應結束后ProgressDialog消失

標籤雲
其他(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