主頁 > 移動端開發 > 詳解 Interpolator影片插值器

詳解 Interpolator影片插值器

2021-09-01 13:07:07 移動端開發

Interpolator 被用來修飾影片效果,定義影片的變化率,在Android原始碼中對應的介面類為TimeInterpolator,通過輸入均勻變化的0~1之間的值,可以得到勻速、正加速、負加速、無規則變加速等0~1之間的變化曲線

曲線舉例:
如下圖所示,為Android原始碼中OvershootInterpolator插值器變化率曲線,
輸入均勻變化0~1.0f之間浮點值,輸出先加速超過臨界值1.0f 再慢慢又回落到1.0f 連續變化的浮點值,

Android原始碼OvershootInterpolator

效果舉例:

使用OvershootInterpolator影片插值器后,影片的運行效果如下所示:

OvershootInterpolator影片插值器運動效果

上圖中,旋轉放大效果中,旋轉影片就是使用了OvershootInterpolator影片插值器,
可以看到3D勛章 360度旋轉時,旋轉角度先超過了360度,然后慢慢又回到了360度位置,從而呈現一個回彈的視覺效果

自定義的精靈影片中使用OvershootInterpolator

注:
了解 3D勛章具體實作,參考文章《3D勛章實作方案》:
https://xiaxl.blog.csdn.net/article/details/77048507

  • Android 原始碼中的影片插值器
  • Easing 經典影片插值器

一、Android中的插值器

Android原始碼中使用 TimeInterpolator 介面修飾影片效果,定義影片的變化率,
代碼位于android.animation包下,只包含一個抽象方法為getInterpolation(float input)

// 位于android.animation包下
package android.animation;
// Android原始碼中的 影片插值器
public interface TimeInterpolator {
	// 差值計算(輸入為0~1.0f之間的浮點值,輸出為連續的變化率曲線)
    float getInterpolation(float input);
}

TimeInterpolator介面類中,只有一個方法float getInterpolation(float input),根據輸入的浮點值input(0~1.0f之間),輸出為連續的變化率曲線,

Android中影片插值器的使用方式如下:

// view 位移影片
AnimatorSet localAnimatorSet = new AnimatorSet();
float[] arrayOfFloat = new float[2];
arrayOfFloat[0] = y0;
arrayOfFloat[1] = y1;
// 位移影片使用了 DecelerateInterpolator() 影片插值器
// 影片效果:先位移超過臨界值,再回到臨界值
ObjectAnimator localObjectAnimator = ObjectAnimator.ofFloat(view,
    "translationY", arrayOfFloat);
localObjectAnimator.setDuration(240L);
localObjectAnimator.setInterpolator(new DecelerateInterpolator());
localAnimatorSet.play(localObjectAnimator);
localAnimatorSet.start();

TimeInterpolator為介面類,其有如下介面實作類,

1.1 AccelerateDecelerateInterpolator

AccelerateDecelerateInterpolator 該插值器運動曲線 兩邊慢 中間快,其運動曲線如下圖所示:

AccelerateDecelerateInterpolator 運動曲線

/**
 * An interpolator where the rate of change starts and ends slowly but
 * accelerates through the middle.
 * 兩邊慢 中間快
 */
public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    public AccelerateDecelerateInterpolator() {
    }

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

1.2 AccelerateInterpolator

AccelerateInterpolator 該插值器運動曲線 先慢 后快,其運動曲線如下圖所示(factor值為1):

AccelerateInterpolator 運動曲線(factor值為1)

/**
 * An interpolator where the rate of change starts out slowly and
 * and then accelerates.
 * 先慢 后快
 */
public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private final float mFactor;
    private final double mDoubleFactor;

    public AccelerateInterpolator() {
        mFactor = 1.0f;
        mDoubleFactor = 2.0;
    }

    /**
     * Constructor
     *
     * @param factor Degree to which the animation should be eased. Seting
     *        factor to 1.0f produces a y=x^2 parabola. Increasing factor above
     *        1.0f  exaggerates the ease-in effect (i.e., it starts even
     *        slower and ends evens faster)
     */
    public AccelerateInterpolator(float factor) {
        mFactor = factor;
        mDoubleFactor = 2 * mFactor;
    }


    public float getInterpolation(float input) {
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            return (float)Math.pow(input, mDoubleFactor);
        }
    }
}

1.3 AnticipateInterpolator

AnticipateInterpolator 該插值器運動曲線 先向后超過臨界值,再快速向前,像一個回蕩的秋千,因此被稱為回蕩秋千插值器曲線圖如下:

AnticipateInterpolator 運動曲線(factor值為1)

/**
 * An interpolator where the change starts backward then flings forward.
 * 先向后 再向前
 */
public class AnticipateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private final float mTension;

    public AnticipateInterpolator() {
        mTension = 2.0f;
    }

    /**
     * @param tension Amount of anticipation. When tension equals 0.0f, there is
     *                no anticipation and the interpolator becomes a simple
     *                acceleration interpolator.
     */
    public AnticipateInterpolator(float tension) {
        mTension = tension;
    }

    public float getInterpolation(float t) {
        // a(t) = t * t * ((tension + 1) * t - tension)
        return t * t * ((mTension + 1) * t - mTension);
    }
}

1.4 AnticipateOvershootInterpolator

AnticipateOvershootInterpolator 該插值器運動曲線 先向后運動 超過臨界值,再快速向前運動到達臨界值,其運動曲線如下圖所示:

AnticipateOvershootInterpolator 運動曲線

/**
 * An interpolator where the change starts backward then flings forward and overshoots
 * the target value and finally goes back to the final value.
 * 先向后運動 超過臨界值,再快速向前運動超過臨界值,最后慢慢回到臨界值
 */
public class AnticipateOvershootInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    private final float mTension;

    public AnticipateOvershootInterpolator() {
        mTension = 2.0f * 1.5f;
    }

    /**
     * @param tension Amount of anticipation/overshoot. When tension equals 0.0f,
     *                there is no anticipation/overshoot and the interpolator becomes
     *                a simple acceleration/deceleration interpolator.
     */
    public AnticipateOvershootInterpolator(float tension) {
        mTension = tension * 1.5f;
    }

    /**
     * @param tension Amount of anticipation/overshoot. When tension equals 0.0f,
     *                there is no anticipation/overshoot and the interpolator becomes
     *                a simple acceleration/deceleration interpolator.
     * @param extraTension Amount by which to multiply the tension. For instance,
     *                     to get the same overshoot as an OvershootInterpolator with
     *                     a tension of 2.0f, you would use an extraTension of 1.5f.
     */
    public AnticipateOvershootInterpolator(float tension, float extraTension) {
        mTension = tension * extraTension;
    }

    private static float a(float t, float s) {
        return t * t * ((s + 1) * t - s);
    }

    private static float o(float t, float s) {
        return t * t * ((s + 1) * t + s);
    }

    public float getInterpolation(float t) {
        // a(t, s) = t * t * ((s + 1) * t - s)
        // o(t, s) = t * t * ((s + 1) * t + s)
        // f(t) = 0.5 * a(t * 2, tension * extraTension), when t < 0.5
        // f(t) = 0.5 * (o(t * 2 - 2, tension * extraTension) + 2), when t <= 1.0
        if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension);
        else return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);
    }
}

1.5 BounceInterpolator

BounceInterpolator 該插值器運動曲線 快速運動到臨界值后,進行幾次回跳,類似一個從高空墜落籃球的運動曲線,其運動曲線如下圖所示:

BounceInterpolator 運動曲線

/**
 * An interpolator where the change bounces at the end.
 * 快速運動到臨界值后,進行幾次回跳,類似一個從高空墜落籃球的運動曲線,
 */
public class BounceInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    public BounceInterpolator() {
    }

    private static float bounce(float t) {
        return t * t * 8.0f;
    }

    public float getInterpolation(float t) {
        // _b(t) = t * t * 8
        // bs(t) = _b(t) for t < 0.3535
        // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408
        // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644
        // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0
        // b(t) = bs(t * 1.1226)
        t *= 1.1226f;
        if (t < 0.3535f) return bounce(t);
        else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
        else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
        else return bounce(t - 1.0435f) + 0.95f;
    }
}

1.6 CycleInterpolator

CycleInterpolator 該插值器運動曲線 正弦變化曲線,其運動曲線如下圖所示:

CycleInterpolator正弦變化曲線

/**
 * Repeats the animation for a specified number of cycles. The
 * rate of change follows a sinusoidal pattern.
 * sin正弦變化曲線
 */
@HasNativeInterpolator
public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private float mCycles;
    
    public CycleInterpolator(float cycles) {
        mCycles = cycles;
    }

    public float getInterpolation(float input) {
        return (float)(Math.sin(2 * mCycles * Math.PI * input));
    }
}

1.7 DecelerateInterpolator

DecelerateInterpolator 該插值器運動曲線 減速插值器變化曲線,其演算法為AccelerateInterpolator的完全倒置,同樣有DecelerateInterpolator(float factor)建構式來指定mFactor運動曲線如下圖所示(factor值為1):

DecelerateInterpolator 減速插值器(factor值為1)

/**
 * An interpolator where the rate of change starts out quickly and
 * and then decelerates.
 * 減速插值器變化曲線,其演算法為AccelerateInterpolator的完全倒置,
 */
public class DecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private float mFactor = 1.0f;
    
    public DecelerateInterpolator() {
    }

    /**
     * Constructor
     *
     * @param factor Degree to which the animation should be eased. Setting factor to 1.0f produces
     *        an upside-down y=x^2 parabola. Increasing factor above 1.0f exaggerates the
     *        ease-out effect (i.e., it starts even faster and ends evens slower).
     */
    public DecelerateInterpolator(float factor) {
        mFactor = factor;
    }

    public float getInterpolation(float input) {
        float result;
        if (mFactor == 1.0f) {
            result = (float)(1.0f - (1.0f - input) * (1.0f - input));
        } else {
            result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));
        }
        return result;
    }
}

1.8 LinearInterpolator

LinearInterpolator 該插值器運動曲線 為0~1之間勻速變化的一條直線,其運動曲線如下圖所示:

LinearInterpolator 勻速變化的一條直線

/**
 * An interpolator where the rate of change starts out quickly and
 * and then decelerates.
 * 為0~1之間勻速變化的一條直線,
 */
/**
 * An interpolator where the rate of change is constant
 */
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public float getInterpolation(float input) {
        return input;
    }
}

1.9 OvershootInterpolator

OvershootInterpolator 該插值器運動曲線 先加速超過臨界值1.0f 再慢慢又回落到1.0f,有一個回彈的效果

可使用OvershootInterpolator(float tension)建構式設定mTension彈力值,mTension值越大,超出目標值的時間點越靠前,超出目標值的回彈距離越大,回彈越明顯,

其運動曲線如下圖所示:

OvershootInterpolator 回彈影片插值器

/**
 * An interpolator where the change flings forward and overshoots the last value
 * then comes back.
 * 先超過臨界值 再慢慢回到臨界值
 */
public class OvershootInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private final float mTension;

    public OvershootInterpolator() {
        mTension = 2.0f;
    }

    /**
     * @param tension Amount of overshoot. When tension equals 0.0f, there is
     *                no overshoot and the interpolator becomes a simple
     *                deceleration interpolator.
     */
    public OvershootInterpolator(float tension) {
        mTension = tension;
    }

    public float getInterpolation(float t) {
        // _o(t) = t * t * ((tension + 1) * t + tension)
        // o(t) = _o(t - 1) + 1
        t -= 1.0f;
        return t * t * ((mTension + 1) * t + mTension) + 1.0f;
    }
}

1.10 PathInterpolator

PathInterpolator 可以稱之為萬能插值器,可以通過PathInterpolator構造一個Path路徑 或 通過傳入點來構造一個貝塞爾曲線(通過這個貝塞爾曲線,我們可以構造任意的變化曲線),

//創建一個任意Path的插值器
PathInterpolator(Path path)
//創建一個二階貝塞爾曲線的插值器
PathInterpolator(float controlX, float controlY)
//創建一個三階貝塞爾曲線的插值器
PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2)

貝塞爾曲線的構建,可以使用如下輔助工具 cubic-bezier:
https://cubic-bezier.com/

cubic-bezier.輔助工具


/**
 * An interpolator that can traverse a Path that extends from <code>Point</code>
 * <code>(0, 0)</code> to <code>(1, 1)</code>. The x coordinate along the <code>Path</code>
 * is the input value and the output is the y coordinate of the line at that point.
 * This means that the Path must conform to a function <code>y = f(x)</code>.
 *
 * <p>The <code>Path</code> must not have gaps in the x direction and must not
 * loop back on itself such that there can be two points sharing the same x coordinate.
 * It is alright to have a disjoint line in the vertical direction:</p>
 * <p><blockquote><pre>
 *     Path path = new Path();
 *     path.lineTo(0.25f, 0.25f);
 *     path.moveTo(0.25f, 0.5f);
 *     path.lineTo(1f, 1f);
 * </pre></blockquote></p>
 * 構造一個普通Path路徑或者貝塞爾曲線的插值器
 */
public class PathInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    // This governs how accurate the approximation of the Path is.
    private static final float PRECISION = 0.002f;

    private float[] mX; // x coordinates in the line

    private float[] mY; // y coordinates in the line

    /**
     * Create an interpolator for an arbitrary <code>Path</code>. The <code>Path</code>
     * must begin at <code>(0, 0)</code> and end at <code>(1, 1)</code>.
     *
     * @param path The <code>Path</code> to use to make the line representing the interpolator.
     */
    public PathInterpolator(Path path) {
        initPath(path);
    }

    public PathInterpolator(float controlX, float controlY) {
        initQuad(controlX, controlY);
    }

    /**
     * Create an interpolator for a cubic Bezier curve.  The end points
     * <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
     *
     * @param controlX1 The x coordinate of the first control point of the cubic Bezier.
     * @param controlY1 The y coordinate of the first control point of the cubic Bezier.
     * @param controlX2 The x coordinate of the second control point of the cubic Bezier.
     * @param controlY2 The y coordinate of the second control point of the cubic Bezier.
     */
    public PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2) {
        initCubic(controlX1, controlY1, controlX2, controlY2);
    }

    private void initQuad(float controlX, float controlY) {
        Path path = new Path();
        path.moveTo(0, 0);
        path.quadTo(controlX, controlY, 1f, 1f);
        initPath(path);
    }

    private void initCubic(float x1, float y1, float x2, float y2) {
        Path path = new Path();
        path.moveTo(0, 0);
        path.cubicTo(x1, y1, x2, y2, 1f, 1f);
        initPath(path);
    }

    private void initPath(Path path) {
        float[] pointComponents = path.approximate(PRECISION);

        int numPoints = pointComponents.length / 3;
        if (pointComponents[1] != 0 || pointComponents[2] != 0
                || pointComponents[pointComponents.length - 2] != 1
                || pointComponents[pointComponents.length - 1] != 1) {
            throw new IllegalArgumentException("The Path must start at (0,0) and end at (1,1)");
        }

        mX = new float[numPoints];
        mY = new float[numPoints];
        float prevX = 0;
        float prevFraction = 0;
        int componentIndex = 0;
        for (int i = 0; i < numPoints; i++) {
            float fraction = pointComponents[componentIndex++];
            float x = pointComponents[componentIndex++];
            float y = pointComponents[componentIndex++];
            if (fraction == prevFraction && x != prevX) {
                throw new IllegalArgumentException(
                        "The Path cannot have discontinuity in the X axis.");
            }
            if (x < prevX) {
                throw new IllegalArgumentException("The Path cannot loop back on itself.");
            }
            mX[i] = x;
            mY[i] = y;
            prevX = x;
            prevFraction = fraction;
        }
    }

    /**
     * Using the line in the Path in this interpolator that can be described as
     * <code>y = f(x)</code>, finds the y coordinate of the line given <code>t</code>
     * as the x coordinate. Values less than 0 will always return 0 and values greater
     * than 1 will always return 1.
     *
     * @param t Treated as the x coordinate along the line.
     * @return The y coordinate of the Path along the line where x = <code>t</code>.
     * @see Interpolator#getInterpolation(float)
     */
    @Override
    public float getInterpolation(float t) {
        if (t <= 0) {
            return 0;
        } else if (t >= 1) {
            return 1;
        }
        // Do a binary search for the correct x to interpolate between.
        int startIndex = 0;
        int endIndex = mX.length - 1;

        while (endIndex - startIndex > 1) {
            int midIndex = (startIndex + endIndex) / 2;
            if (t < mX[midIndex]) {
                endIndex = midIndex;
            } else {
                startIndex = midIndex;
            }
        }

        float xRange = mX[endIndex] - mX[startIndex];
        if (xRange == 0) {
            return mY[startIndex];
        }

        float tInRange = t - mX[startIndex];
        float fraction = tInRange / xRange;

        float startY = mY[startIndex];
        float endY = mY[endIndex];
        return startY + (fraction * (endY - startY));
    }
}

1.11 OvershootInterpolator

OvershootInterpolator 該插值器運動曲線 先加速超過臨界值1.0f 再慢慢又回落到1.0f,有一個回彈的效果

可使用OvershootInterpolator(float tension)建構式設定mTension彈力值,mTension值越大,超出目標值的時間點越靠前,超出目標值的回彈距離越大,回彈越明顯,

其運動曲線如下圖所示:

OvershootInterpolator 回彈影片插值器

/**
 * An interpolator where the change flings forward and overshoots the last value
 * then comes back.
 * 先超過臨界值 再慢慢回到臨界值
 */
public class OvershootInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private final float mTension;

    public OvershootInterpolator() {
        mTension = 2.0f;
    }

    /**
     * @param tension Amount of overshoot. When tension equals 0.0f, there is
     *                no overshoot and the interpolator becomes a simple
     *                deceleration interpolator.
     */
    public OvershootInterpolator(float tension) {
        mTension = tension;
    }

    public float getInterpolation(float t) {
        // _o(t) = t * t * ((tension + 1) * t + tension)
        // o(t) = _o(t - 1) + 1
        t -= 1.0f;
        return t * t * ((mTension + 1) * t + mTension) + 1.0f;
    }
}

注:
使用PathInterpolator插值器會消耗更多的記憶體,不同于其他簡單插值器,一般的插值器都是在演算法上來生成插值,而PathInterpolator是在初始化時依賴Path演算法生成一系列插值點存盤,原始碼顯示是以0.02為step在0到1范圍內取點,生成500個x樣本和500個y樣本共計1000個float資料,相比其他插值器消耗了相當1000倍的記憶體,雖然對目前手機性能來說微不足道,但在影片這種要求高性能的操作時建議謹慎使用,不要頻繁初始化,盡量復用同引數的插值器,以提高性能,

二、Easing 插值器

Easing演算法是業界著名的一組插值器演算法,涵蓋了各種速率的曲線演算法,
其涵蓋的曲線演算法如下圖所示:

Easing 插值器

注:
easings 官方網址:
https://easings.net/

easeInOutBounce

舉例一個影片插值器 easeInOutBounce,Easing官方對于每一個影片插值器,均給出了完整的演算法實作影片運動曲線,開發者可以根據自己的需要自行選擇對應的插值器演算法,構造自己的影片插值器,

easeInOutBounce

function easeInOutBounce(x: number): number {
return x < 0.5
  ? (1 - easeOutBounce(1 - 2 * x)) / 2
  : (1 + easeOutBounce(2 * x - 1)) / 2;
}

三、除錯插值器

除錯影片插值器,可以使用如下小工具:

wolframalpha 除錯影片插值器:
https://www.wolframalpha.com/input/?i=x%5E%282*3%29%280%3Cx%3C%3D1%29

wolframalpha 除錯插值器

參考

wolframalpha除錯工具:
https://www.wolframalpha.com/input/?i=x%5E%282*3%29%280%3Cx%3C%3D1%29

cubic-bezier輔助工具:
https://cubic-bezier.com/

easings 插值器:
https://easings.net/

3D勛章實作方案:
https://xiaxl.blog.csdn.net/article/details/77048507

= THE END =

歡迎關注我的公眾號

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

標籤:其他

上一篇:MVVM框架模式

下一篇:百度地圖開發-繪制點線提示框 07

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