Android用户界面:TransitionDrawable

3

如何在代码中使用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);
        }
    };
}

我的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>

让我们先从基于XML的代码部分开始(也就是注释掉纯编程代码行)。

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

整个setDrawableByLayerId()方法很令人困惑。在构造函数中,您需要指定一个Drawables列表,这些Drawables将进入一个LayerDrawable中。我认为这些就是所谓的索引。那么如果它不是这种索引,那么id又是什么呢?

我尝试向“item”标记添加android:id属性。虽然这段代码可以构建,但无法运行。因此,id不是通常使用的那个id。

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

id似乎只是一些数字(可能在LayerDrawable中很重要),可以用setId(index,id)设置,并使用getId(index)获取。默认情况下,不会分配任何ID。并且您可以保留未添加图层的ID。在我的代码中,两个getId()调用都返回-1,这就是为什么使用setDrawableByLayerId(-1,...)仅有最后一个粘住的原因。确实,注释掉最后一行会产生不同的行为,从trans1到trans3的转换。

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

transition.setId(0, 50);
transition.setId(1, 51);

我的概念有什么问题,以至于我必须让它变得如此复杂才能使其工作?

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

让我们尝试纯编程代码。它是等效的。实际上,它立即放入了正确的可绘制对象。

现在,在这个示例应用程序中,它给出了相同的结果。然而,在我的应用程序中(其中相关代码过于复杂,无法在此处发布),我仍然有一个问题:

如果我尝试使用来自xml指定的转换的预编程可绘制对象,我会发现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)

我在这里缺失了什么?与 mutate() 有关的内容吗?

我提到我还想分两步设置图层,并完全使用代码进行。这意味着我首先必须执行

transition = new TransitionDrawable(new Drawable[] {<1>});

仅传递一个图层时可以实现。但是,我无法对新图层执行setId()操作,因此无法稍后添加新图层(尽管通过阅读setDrawableByLayerId()的文档,您可能会认为您可以这样做)。

通过以2个元素的数组形式直接传入第二个图层,并将第二个元素设置为null,则会受到惩罚,因此我将只传入与第一个图层相同的可绘制对象。

我是否有遗漏的部分,或者还有更简单的方法可以完成这个任务?


不用在意setAlpha()在交叉淡入淡出时没有任何效果。我在重写的可绘制对象中没有传递paint。我已经从我的问题中删除了它。 - pjv
1个回答

5
我建议您创建一个新的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;

}

然后调用:

mImageView.setImageDrawable( mTransitionDrawable );

1
这个问题已经存在了三年。我不确定该怎么做……同时,创建一个新的TransitionDrawable已经是我的问题的一部分了。 - pjv
看起来你在问题中使用了一个从资源XML中解压的TransitionDrawable。我建议创建一个全新的。 - Vaiden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接