andbook!.pdf - Learning Android Get an anddev.org - Android-Shirt Back to index
anddev.org Header Logo
FAQ Search Top rated articles Browse Feeds anddev.org - Authors Contact Details Register Log in

Custom View w/ EditTexts: state being overwritten


 
       anddev.org - Android Development Community | Android Tutorials | Index -> View, Layout & Resource Problems
Author Message
divestoclimb
Developer
Developer


Joined: 11 May 2009
Posts: 33

PostPosted: Mon Sep 28, 2009 6:08 am    Post subject: Custom View w/ EditTexts: state being overwritten Reply with quote

I'm trying to figure out how to properly make a custom view consisting of a LinearLayout and some children, one of which is a EditText. To make this simple, I've pared down the code to the simplest possible case.

res/layout/bughunt.xml is a basic definition of a custom view; it's just a layout with a single EditText inside.
XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">

     <EditText
          android:id="@+id/text1"
          android:layout_width="wrap_content"
          android:layout_height="40sp"
          android:gravity="center"
          android:width="50sp"
          android:singleLine="true"/>

</LinearLayout>

My custom view class:
Java:

public class BugHunt extends LinearLayout {

     public BugHunt(Context context) {
          super(context);
          initLayout(context);
     }

     public BugHunt(Context context, AttributeSet attrs) {
          super(context, attrs);
          initLayout(context);
     }

     private void initLayout(Context context) {
          LayoutInflater i = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          i.inflate(R.layout.bughunt, this);
     }
}

Then I put two instances like the following in an Activity layout file:
XML:

<my.package.BugHunt
     layout_width="wrap_content"
     layout_height="wrap_content" />


The problem I'm having is when the EditTexts save state, they overwrite each other's state. To reproduce this, put two or more instances of BugHunt into an Activity, run it, and enter some (different) text into each EditText. Then, switch the screen orientation. After the layout is redrawn, all EditTexts will have the same text in them (the text from whichever EditText saved state last).

I can only guess that I'm not using the LayoutInflater properly. Any ideas?
Back to top
View user's profile Send private message
divestoclimb
Developer
Developer


Joined: 11 May 2009
Posts: 33

PostPosted: Mon Sep 28, 2009 3:19 pm    Post subject: Reply with quote

I got a reply on android-developers that this is the result of having the same ID for each EditText. I'm devising a method to work around this and will post it here for everyone's benefit when I get it working.
Back to top
View user's profile Send private message
divestoclimb
Developer
Developer


Joined: 11 May 2009
Posts: 33

PostPosted: Tue Sep 29, 2009 2:34 am    Post subject: Reply with quote

Here's the 90% solution.

First, I abstracted a bit of processing into a separate class called ViewId, which generates an ID unique within the passed View:
Java:

public class ViewId {

     public static int generateUnique(View v) {
          Random r = new Random();
          
          int id;
          do {
               id = r.nextInt();
          } while(v.findViewById(id) != null);
          return id;
     }
}


Then I made these changes in my example BugHunt class:
Java:

     private void initLayout(Context context) {
          LayoutInflater i = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          i.inflate(R.layout.bughunt, this);

          mEditText = (EditText)findViewById(R.id.text1);
          setEditTextId(ViewId.generateUnique(getRootView()));
     }
     
     protected void setEditTextId(int id) {
          mEditText.setId(id);
     }


This allows the EditText to always have a unique ID after the layout is inflated. This is only half the solution, though, because when the Activity is recreated the EditText will get assigned a different random ID. To handle that, I had to override the onSaveInstanceState and onRestoreInstanceState methods to save/restore the ID in a custom SavedState object (code borrowed heavily from TextView):

Java:

     public static class SavedState extends BaseSavedState {
          int textId;
          
          SavedState(Parcelable superState) {
               super(superState);
          }
          
          @Override
          public void writeToParcel(Parcel out, int flags) {
               super.writeToParcel(out, flags);
               
               out.writeInt(textId);
          }
          
          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];
               }
          };

          private SavedState(Parcel in) {
               super(in);
               textId = in.readInt();
          }
     }

     @Override
     public Parcelable onSaveInstanceState() {
          Parcelable superState = super.onSaveInstanceState();

          SavedState ss = new SavedState(superState);
          ss.textId = mEditText.getId();

          return ss;
     }

     @Override
     public void onRestoreInstanceState(Parcelable state) {
          SavedState ss = (SavedState)state;
          super.onRestoreInstanceState(ss.getSuperState());

          setEditTextId(ss.textId);
     }


The only thing not working here is that focus won't get restored to the EditText, which is weird because adb logcat usually shows that the Window fails to find the ID after it's already been set. I don't really care though, this is enough for me. Hopefully this helps somebody, and hopefully this sort of thing will be made easier in future revisions of the API.
Back to top
View user's profile Send private message
Display posts from previous:   
       anddev.org - Android Development Community | Android Tutorials | Index -> View, Layout & Resource Problems All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum


© 2007, Android Development Community
All rights reserved.
Powered by phpBB.