Android UI:TransitionDrawable

发布于 2024-10-09 23:27:44 字数 4882 浏览 1 评论 0原文

在代码中使用 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() 方法令人困惑。在构造函数中,您将指定进入 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);

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

我真正想要在我的真实应用程序中做的是不使用任何 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)

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

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

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

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

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

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

What's the intended way to use a TransitionDrawable in code? Any examples?

I made a small test app to lay down some context:

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);
        }
    };
}

and my TransitionDrawable xml file looks like:

<?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>

Let's first start with the XML-based code part (so that means comment out the Pure programmatic code line).

If you run this code and press the button, then you see he image change from trans1 to trans4, instead of from trans3. Why isn't the initial drawable replaced?

The whole setDrawableByLayerId() method is confusing. In the constructor you'd specify a list of Drawables that goes into a LayerDrawable. I suppose these are what is referred to as indexes. Then what is an id if it is not such an index?

I tried adding android:id attributes to the "item" tags. While this code builds, it does not run. So id is not this id, that you'd normally have.

Perhaps it is the resId of the current drawable in that position? That doesn't seem either.

Id seems to be just some number (maybe it matters in a LayerDrawable) that can be set with setId(index, id) and gotten with getId(index). By default no ids are assigned. And you can reserve none for layers that have not been added yet. In my code both getId() calls return -1, which is why when using setDrawableByLayerId(-1, ...) only the last one sticks. Indeed commenting out the last line gives different behavior, giving a transition from trans1 to trans3.

How can I change the first drawable layer? I have to add the following code before the setDrawableByLayerId(). Even when I don't use 50 or 51 anywhere. This makes it go from trans3 to trans4.

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

What is wrong about my concepts that I have to make it this complicated to get it to work?

What I actually wanted to do in my real app was not use any xml code, I see no use for it. I'd also like to first add in the first layer, and only later, after construction, put in the second layer, but we'll continue with that later.

Let's try the pure programmatic code. It is equivalent. In fact it puts in the right Drawables right away.

Now, in this sample app it gives the same result. However, in my app (of which the relevant code is too complex to post here), I still have a problem:

If I try with preprogrammed Drawables from an xml-specified transition, I get that getResources().getDrawable(R.drawable.trans) the second time returns 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)

What am I missing here? Something with missing mutate()?

I mentioned I'd also like to set the layers in two steps, and fully in code. Meaning I'd first have to do

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

with passing in only one layer. However I cannot do setId() on a new layer, so I can't add a new layer later on (although reading the documentation for setDrawableByLayerId() would lead you to believe you could).

Passing in a second layer straight away, by means of an array of 2 with second element null, is punished, so I'll just pass in the same drawable as the first layer then.

Anything I've been missing here and could have done easier?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

才能让你更想念 2024-10-16 23:27:44

我建议简单地创建一个新的 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;

}

然后调用:

mImageView.setImageDrawable( mTransitionDrawable );

I recommend simply creating a new TransitionDrawable instead of "raping" your old one. I do that all the time:

Here is a code snippet of mine that creates a TransitionDrawable for the sharing button:

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;

}

And then call:

mImageView.setImageDrawable( mTransitionDrawable );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文