0

i try to Code a Custom View in Android Studio. So far so god.

Everything works fine, except to save the Instance of the View.

The View Contains 4 Elements

  • Linear Layout (what contains 2 TextViews)
  • ImageView

after rotating the screen or press Back and reopen the App, the ImageView doesn't save it's state/image. It restores is default Image!

I have tried multiple ways But Nothing works.

The onSaveInstanceState() and the onRestoreInstanceState(Parcelable) are never called and i don't know why :(

Hope you can help me.

#edit: Add GIF of the Problem GIF of Problem

Here's my code so far:

package de.codersgen.activitycontrol;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Created by Ben Ny on 21.02.2017.
 */

public class ActivityView extends LinearLayout {

    private Context context;

    private static String STATE_SUPER_CLASS = "ActivitySuperClass";
    private static String STATE_HEADER_TEXT = "HeaderText";
    private static String STATE_INFO_TEXT = "InfoText";
    private static String STATE_STATUS_IMAGE = "StatusImage";

    private LinearLayout mTextContainer;
    private TextView mHeaderText;
    private TextView mInfoText;
    private ImageView mStatusImage;
    private int state = 0;
    private int[] stateImages = {
            R.drawable.infosign_black_24dp,
            R.drawable.check_black_24dp
    };

    public ActivityView(Context context) {
        super(context);
        this.context = context;
        initializeViews(context);
    }

    public ActivityView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        initializeViews(context);
    }

    public ActivityView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        initializeViews(context);
    }

    private void initializeViews(Context context) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.container_view, this);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mTextContainer = (LinearLayout) this
                .findViewById(R.id.textContainer);
        mHeaderText = (TextView) this
                .findViewById(R.id.headerText);
        mInfoText = (TextView) this
                .findViewById(R.id.infoText);
        mStatusImage = (ImageView) this
                .findViewById(R.id.statusImage);
        mStatusImage
                .setBackgroundResource(android.R.drawable.ic_media_next);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        super.onSaveInstanceState();
        Toast.makeText(context, "SAVE", Toast.LENGTH_SHORT).show();
        Bundle bundle = new Bundle();
        bundle.putParcelable(STATE_SUPER_CLASS,
                            super.onSaveInstanceState());
        bundle.putString(STATE_HEADER_TEXT, mHeaderText.getText().toString());
        bundle.putString(STATE_INFO_TEXT, mInfoText.getText().toString());
        bundle.putInt(STATE_STATUS_IMAGE, state);
        return bundle;
    }


    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            super.onRestoreInstanceState(bundle.getParcelable(STATE_SUPER_CLASS));
            setHeaderText("TEST");
            setInfotext(bundle.getString(STATE_INFO_TEXT));
            if (bundle.getInt(STATE_STATUS_IMAGE) == 1)
                setStatusFinish();
            else
                setStatusUnfinished();
        }
        else {
            super.onRestoreInstanceState(state);
        }
    }

    @Override
    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
        super.dispatchFreezeSelfOnly(container);
    }

    @Override
    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
        super.dispatchThawSelfOnly(container);
    }

    public String getHeaderText() {
        mHeaderText = (TextView) this
                .findViewById(R.id.headerText);
        return mHeaderText.getText().toString();
    }

    public void setHeaderText(String text) {
        mHeaderText = (TextView) this
                .findViewById(R.id.headerText);
        mHeaderText.setText(text);
    }

    public String getInfoText() {
        mInfoText = (TextView) this
                .findViewById(R.id.infoText);
        return mInfoText.getText().toString();
    }

    public void setInfotext(String text) {
        mInfoText = (TextView) this
                .findViewById(R.id.infoText);
        mInfoText.setText(text);
    }

    public void setStatusUnfinished() {
        mStatusImage = (ImageView) this
                .findViewById(R.id.statusImage);
        state = 0;
        mStatusImage.setImageResource(R.drawable.infosign_black_24dp);
    }

    public void setStatusFinish() {
        mStatusImage = (ImageView) this
                .findViewById(R.id.statusImage);
        state = 1;
        mStatusImage.setImageResource(R.drawable.check_black_24dp);
    }

    public void setStatusOnClickListener(OnClickListener listener) {
        mStatusImage = (ImageView) this
                .findViewById(R.id.statusImage);
        mStatusImage.setOnClickListener(listener);
    }
}

edit number2: Add the XML of my CustomView

    <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:id="@+id/textContainer"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1">
        <TextView
            android:id="@+id/headerText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:textColor="@android:color/black"
            android:text="Example Header"
            android:textSize="19sp">
        </TextView>

        <TextView
            android:id="@+id/infoText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/holo_red_dark"
            android:paddingLeft="10dp"
            android:paddingBottom="3dp"
            android:text="Info Header"
            android:textSize="12sp">
        </TextView>
    </LinearLayout>
    <ImageView
        android:id="@+id/statusImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:padding="5dp"
        android:src="@drawable/add_black_24dp"
        android:layout_weight="0.001">
    </ImageView>
</merge>
  • I don't know why you are creating a custom view instead of using RecyclerView or ListView. – Myat Min Soe Feb 21 '17 at 21:34
  • Check [this](http://stackoverflow.com/a/3542895/5993410) – Atef Hares Feb 21 '17 at 21:38
  • I add the View not in the Designer. I add they while my app is Runing. So it is easier to control this why. @AtefHares this don't help me. Because the Funcions are never called. :( – Benjamin S. Feb 21 '17 at 21:43
  • you must assign an ID in order to work. http://stackoverflow.com/a/28586444/3300893 – Myat Min Soe Feb 21 '17 at 21:45
  • @septemberboy7 can't add an ID to "merge" element in my XML file... Edit my XML file above.. :/ – Benjamin S. Feb 21 '17 at 21:49
  • you should add id to your custom view when it is used. – Myat Min Soe Feb 21 '17 at 21:52
  • I add it while the APP is Running. So i have to use: testView.setId(int). But my Problem is how to give them an Unique ID? Count a Integer up? Or something like this? what means i have to save an other thing... ~.~ this makes me go crazy xD – Benjamin S. Feb 21 '17 at 21:56

1 Answers1

0

You can add a stylable property which could represent your "count" then in the layout constructor get the stylable and increment the "count"

Loren Rogers
  • 325
  • 3
  • 13
  • did you have an example of what you mean? Don't unterstand what you mean :/ – Benjamin S. Feb 21 '17 at 22:34
  • In attrs.xml add: ` ` Then in your layout xml, add: `xmlns:custom="http://schemas.android.com/apk/res-auto"`. You would do that if you wanted your xml to get access to custom:counter. Otherwise in the layoutfile.java that extends your layout, there are 2 constructors that take the AttributeSet param. `TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.Identifier, 0, 0); Integer counter = a.getInt(R.styleable.Identifier_counter); a.recycle();` – Loren Rogers Feb 22 '17 at 14:17