Android UI:TransitionDrawable

pjv*_*pjv 3 user-interface android transition

在代码中使用 TransitionDrawable 的预期方式是什么?有什么例子吗?

我制作了一个小型测试应用程序来奠定一些背景:

public class SkeletonActivity extends Activity {
    private Button b;
    private ImageView iv;
    private TransitionDrawable transition;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Inflate our UI from its XML layout description.
        setContentView(R.layout.skeleton_activity);

        // Hook up button presses to the appropriate event handler.
        b = ((Button) findViewById(R.id.button));
        b.setOnClickListener(mButtonListener);
        iv = ((ImageView) findViewById(R.id.image));

        //XML-based code
        transition = (TransitionDrawable)getResources().getDrawable(R.drawable.trans).mutate();
        transition.setDrawableByLayerId(transition.getId(0), getResources().getDrawable(R.drawable.trans3));
        transition.setDrawableByLayerId(transition.getId(1), getResources().getDrawable(R.drawable.trans4));

        //Pure programmatic code
        transition = new TransitionDrawable(new Drawable[] {getResources().getDrawable(R.drawable.trans3), getResources().getDrawable(R.drawable.trans4)});

        transition.setCrossFadeEnabled(true);
    }

    OnClickListener mButtonListener = new OnClickListener() {
        public void onClick(View v) {
            iv.setImageDrawable(transition);
            transition.startTransition(5000);
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

我的 TransitionDrawable xml 文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/trans1" />
    <item android:drawable="@drawable/trans2" />
</transition>
Run Code Online (Sandbox Code Playgroud)

让我们首先从基于 XML 的代码部分开始(这意味着注释掉纯编程代码行)。

如果运行此代码并按下按钮,您会看到图像从 trans1 更改为 trans4,而不是从 trans3。为什么最初的可绘制对象没有被替换?

整个 setDrawableByLayerId() 方法令人困惑。在构造函数中,您将指定进入 LayerDrawable 的 Drawable 列表。我想这些就是所谓的索引。那么如果不是这样的索引,id又是什么?

我尝试将 android:id 属性添加到“item”标签中。当此代码生成时,它不会运行。所以 id 不是您通常拥有的这个 id。

也许是该位置当前可绘制对象的 resId?这似乎也不是。

Id 似乎只是一些数字(也许在 LayerDrawable 中很重要),可以使用 setId(index, id) 设置并使用 getId(index) 获取。默认情况下不分配 id。对于尚未添加的图层,您可以不保留任何内容。在我的代码中,两个 getId() 调用都返回 -1,这就是为什么在使用 setDrawableByLayerId(-1, ...) 时仅保留最后一个。事实上,注释掉最后一行会产生不同的行为,从而实现从 trans1 到 trans3 的过渡。

如何更改第一个可绘制层?我必须在 setDrawableByLayerId() 之前添加以下代码。即使我在任何地方都不使用 50 或 51。这使得它从 trans3 变为 trans4。

transition.setId(0, 50);
transition.setId(1, 51);
Run Code Online (Sandbox Code Playgroud)

我的想法有什么问题,我必须让它变得如此复杂才能让它发挥作用?

我真正想要在我的真实应用程序中做的是不使用任何 xml 代码,我认为它没有用处。我还想先添加第一层,然后在构建完成后,再添加第二层,但我们稍后会继续。

让我们尝试一下纯编程代码。这是等价的。事实上,它会立即放入正确的 Drawable。

现在,在此示例应用程序中,它给出了相同的结果。但是,在我的应用程序中(相关代码太复杂,无法在此发布),我仍然遇到问题:

如果我尝试从 xml 指定的转换中使用预编程的 Drawable,我会发现 getResources().getDrawable(R.drawable.trans) 第二次返回 null:

12-30 21:35:32.970: ERROR/AndroidRuntime(7457): java.lang.NullPointerException
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.LayerDrawable$LayerState.<init>(LayerDrawable.java:581)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.TransitionDrawable$TransitionState.<init>(TransitionDrawable.java:235)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.TransitionDrawable.createConstantState(TransitionDrawable.java:99)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.LayerDrawable.<init>(LayerDrawable.java:94)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.TransitionDrawable.<init>(TransitionDrawable.java:90)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.TransitionDrawable.<init>(TransitionDrawable.java:39)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.graphics.drawable.TransitionDrawable$TransitionState.newDrawable(TransitionDrawable.java:245)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.content.res.Resources.getCachedDrawable(Resources.java:1753)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.content.res.Resources.loadDrawable(Resources.java:1664)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at android.content.res.Resources.getDrawable(Resources.java:581)
12-30 21:35:32.970: ERROR/AndroidRuntime(7457):     at net.lp.collectionista.ui.views.CoverView.updateCover(CoverView.java:78)
Run Code Online (Sandbox Code Playgroud)

我在这里缺少什么?缺少 mutate() 的东西吗?

我提到我还想分两步设置图层,并且完全用代码来设置。这意味着我首先要做的

transition = new TransitionDrawable(new Drawable[] {<1>});
Run Code Online (Sandbox Code Playgroud)

仅传递一层。但是,我无法在新图层上执行 setId() ,因此稍后我无法添加新图层(尽管阅读 setDrawableByLayerId() 的文档会让您相信您可以)。

通过第二个元素为空的 2 数组直接传递第二层会受到惩罚,所以我将传递与第一层相同的可绘制对象。

我在这里遗漏了什么并且可以做得更容易吗?

Vai*_*den 5

我建议简单地创建一个新的 TransitionDrawable,而不是“强奸”旧的 TransitionDrawable。我一直这样做:

这是我的代码片段,为共享按钮创建 TransitionDrawable:

private TransitionDrawable createIconTransition( SharingStates layer1, SharingStates layer2 )
{
    Resources res = getContext().getResources();

    TransitionDrawable out = new TransitionDrawable( new Drawable[] { res.getDrawable( layer1.mIconId ), res.getDrawable( layer2.mIconId )} );
    out.setCrossFadeEnabled( true );

    return out;

}
Run Code Online (Sandbox Code Playgroud)

然后调用:

mImageView.setImageDrawable( mTransitionDrawable );
Run Code Online (Sandbox Code Playgroud)