Android 自定义/复合控件:可共享状态是共享的,但不应该共享?

发布于 2024-12-18 19:07:28 字数 3105 浏览 0 评论 0原文

我在 Android 应用程序中创建了一个自定义视图/复合控件,它允许用户“绘制”他们的签名。

签名包含在画布中,链接到位图对象。

我希望在方向改变时保留签名“图像”。因此,我通过存储位图的像素来实现 onSaveInstanceState / onRestoreInstanceState:

@Override
public Parcelable onSaveInstanceState()
{
    // Call superclass method, retrieve Parcelable
    Parcelable superState = super.onSaveInstanceState();

    if (pictureBitmap_ != null)
    {
        // Retrieve the current pixels array.
        int totalSize = pictureBitmap_.getWidth()
                * pictureBitmap_.getHeight();

        int pixels[] = new int[totalSize];

        pictureBitmap_.getPixels(pixels,
            0,
            pictureBitmap_.getWidth(),
            0,
            0,
            pictureBitmap_.getWidth(),
            pictureBitmap_.getHeight());

        // Create the saved state object.
        SavedState savedState = new SavedState(superState);
        savedState.pixels = pixels;

        // Return the populated saved state object.
        return savedState;
    }
    else
    {
        // Simply pass original Parcelable along
        return superState;
    }
}

@Override
public void onRestoreInstanceState(Parcelable state)
{
    // Is the Parcelable an instance of our custom SavedState?
    if (!(state instanceof SavedState))
    {
        // No, simply delegate to superclass.
        super.onRestoreInstanceState(state);
        return;
    }

    // Retrieve custom state object.
    SavedState savedState = (SavedState) state;

    // Use superclass to restore original state.
    super.onRestoreInstanceState(savedState.getSuperState());

    // Restore custom state (transfer pixels).
    this.transferPixels_ = savedState.pixels;

    // If the picture bitmap is already initialized...
    if (pictureBitmap_ != null)
    {
        // Transfer the pixels right away.
        transferBitmap();

        // Refresh the canvas
        drawSignature();
    }
}

像素的整数数组存储在 SavedState 对象中,该对象是 BaseSavedState 的自定义子类:

private static class SavedState
        extends BaseSavedState
{
    // Members
    int[] pixels;

    // Methods
    SavedState(Parcelable superState)
    {
        super(superState);
    }

    private SavedState(Parcel in)
    {
        super(in);
        in.readIntArray(pixels);
    }

    @Override
    public void writeToParcel(Parcel out, int flags)
    {
        super.writeToParcel(out, flags);
        out.writeIntArray(pixels);
    }

    // required field that makes Parcelables from a Parcel
    @SuppressWarnings("unused")
    public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>()
    {
        public SavedState createFromParcel(Parcel in)
        {
            return new SavedState(in);
        }

        public SavedState[] newArray(int size)
        {
            return new SavedState[size];
        }
    };
}

现在,如果我只有一 (1) 个实例,则此方法运行良好我的活动中的自定义视图...如果我有两 (2) 个或更多实例,则会出现问题:当我翻转方向时,我的所有控件最终都会显示相同的签名,这是最后一个控件的签名。

换句话说,存储在 SavedState 对象中的最后一组像素似乎成为我的 Activity 中所有控件实例的“通用”像素组。

如何确保每个控件都有自己独立的保存状态?

I have created a custom View / Compound Control in my Android application, which lets users "draw" their signature.

The signature is contained in a Canvas, linked to a Bitmap object.

I want the signature "image" to be preserved when the orientation is changed. Therefore, I have implemented onSaveInstanceState / onRestoreInstanceState by storing the Bitmap's pixels:

@Override
public Parcelable onSaveInstanceState()
{
    // Call superclass method, retrieve Parcelable
    Parcelable superState = super.onSaveInstanceState();

    if (pictureBitmap_ != null)
    {
        // Retrieve the current pixels array.
        int totalSize = pictureBitmap_.getWidth()
                * pictureBitmap_.getHeight();

        int pixels[] = new int[totalSize];

        pictureBitmap_.getPixels(pixels,
            0,
            pictureBitmap_.getWidth(),
            0,
            0,
            pictureBitmap_.getWidth(),
            pictureBitmap_.getHeight());

        // Create the saved state object.
        SavedState savedState = new SavedState(superState);
        savedState.pixels = pixels;

        // Return the populated saved state object.
        return savedState;
    }
    else
    {
        // Simply pass original Parcelable along
        return superState;
    }
}

@Override
public void onRestoreInstanceState(Parcelable state)
{
    // Is the Parcelable an instance of our custom SavedState?
    if (!(state instanceof SavedState))
    {
        // No, simply delegate to superclass.
        super.onRestoreInstanceState(state);
        return;
    }

    // Retrieve custom state object.
    SavedState savedState = (SavedState) state;

    // Use superclass to restore original state.
    super.onRestoreInstanceState(savedState.getSuperState());

    // Restore custom state (transfer pixels).
    this.transferPixels_ = savedState.pixels;

    // If the picture bitmap is already initialized...
    if (pictureBitmap_ != null)
    {
        // Transfer the pixels right away.
        transferBitmap();

        // Refresh the canvas
        drawSignature();
    }
}

The integer array of pixels is stored in a SavedState object, which is a custom subclass of BaseSavedState:

private static class SavedState
        extends BaseSavedState
{
    // Members
    int[] pixels;

    // Methods
    SavedState(Parcelable superState)
    {
        super(superState);
    }

    private SavedState(Parcel in)
    {
        super(in);
        in.readIntArray(pixels);
    }

    @Override
    public void writeToParcel(Parcel out, int flags)
    {
        super.writeToParcel(out, flags);
        out.writeIntArray(pixels);
    }

    // required field that makes Parcelables from a Parcel
    @SuppressWarnings("unused")
    public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>()
    {
        public SavedState createFromParcel(Parcel in)
        {
            return new SavedState(in);
        }

        public SavedState[] newArray(int size)
        {
            return new SavedState[size];
        }
    };
}

Now, while this is working well if I only have ONE (1) instance of my custom view in my activity... a problem occurs if I have TWO (2) or more instances: when I flip the orientation, all my controls end up displaying the same signature, which was the last control's signature.

In other words, the last set of pixels stored in a SavedState object appears to become the "universal" set of pixels for all my control instances within my Activity.

How do I ensure that each control has its own independent saved state?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文