切换方向后复选框全部显示相同的文本

发布于 2024-11-06 23:30:57 字数 4822 浏览 0 评论 0原文

编辑:查看已接受的答案。教训:有时视图会自动保存和恢复其状态。这发生在 onCreate 之后。这可能会导致您在 onCreate 中所做的事情被覆盖。如果您没有唯一的 ID,则可以使用相同的保存状态覆盖某种类型的所有视图(在我的例子中是文本框)。(ps:感谢大家的帮助!)

所以,我有一个简单的方法线性布局,我想添加一些带有图像复选框的视图。一切正常,直到我切换 Android 手机的方向。当我这样做时,它会返回到 onCreate,但这次复选框都以相同的文本结束。奇怪的是,图像看起来很好。

我的问题是:为什么要这样做?我怎样才能让它每次都像第一次一样?

如果这没有意义,这里有一个例子:(编辑:事实证明它总是显示最后一个元素的文本)

我首先看到的

[] a *a's image*
[] b *b's image*
[] c *c's image*
[] d *d's image*

然后,旋转我的手机后,它重新绘制

[] d *a's image*
[] d *b's image*
[] d *c's image*
[] d *d's image*

我的原始代码非常复杂,但我构建了以下内容这说明了问题所在。

Main.java:AnswerView.java

public class Main extends Activity {

ArrayList<AnswerView> answers = new ArrayList<AnswerView>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    TextView title = (TextView)findViewById(R.id.questionText);
    title.setText("This is a test");
    HashMap<String, Drawable> answerInfo = new HashMap<String, Drawable>();
    Resources res = getResources();
    answerInfo.put("a", res.getDrawable(R.drawable.flower_orange));
    answerInfo.put("b", res.getDrawable(R.drawable.flower_white));
    answerInfo.put("c", res.getDrawable(R.drawable.leaf));
    answerInfo.put("d", res.getDrawable(R.drawable.flower_yellow));
    setBoxes(answerInfo);
}

private void setBoxes(HashMap<String, Drawable> answerInfo) {
    LinearLayout answerList = (LinearLayout)findViewById(R.id.answerlist);
    AnswerView cb = null;

    //Remove all existing answer views
    answerList.removeAllViews();
    answers.clear();

    //For each possible answer create a answer views
    for (String s : answerInfo.keySet()) {
        cb = new AnswerView(this, s, answerInfo.get(s));
        answers.add(cb);
        String text = cb.getText();
        answerList.addView(cb);
    }
}
}

image_checkbox.xml

 public class AnswerView extends RelativeLayout  {

private CheckBox m_checkbox;
private ImageView m_image;
//private Context m_context;

public AnswerView(Context context, String answer, Drawable d) {
    super(context);
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.image_checkbox, this, true);
    m_checkbox = (CheckBox) view.findViewById(R.id.image_checkbox_cb);
    m_image = (ImageView) view.findViewById(R.id.image_checkbox_img);
    //m_context = context;
    m_checkbox.setText(answer);
    m_image.setImageDrawable(d);
    m_image.setVisibility(VISIBLE);

}

public void setChecked(boolean checked) {
    m_checkbox.setChecked(checked);
}

public boolean isChecked() {
    return m_checkbox.isChecked();
}

public String getText() {
    return m_checkbox.getText().toString();
}

}

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
        android:layout_height="wrap_content">
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" 
  android:padding="5dip">

  <TextView android:orientation="vertical" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/questionText"
    android:textSize="18sp"/>

  <LinearLayout android:orientation="vertical" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/answerlist"/>
  <LinearLayout android:orientation="horizontal" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center">
    <Button  
    android:layout_width="200dip" 
    android:layout_height="wrap_content" 
    android:text="Enter"
    android:id="@+id/buttonAnswerEnter"/>
    />
    </LinearLayout>

</LinearLayout>
</ScrollView>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="horizontal">
  <CheckBox
   android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:id="@+id/image_checkbox_cb"></CheckBox>
  <ImageView
  android:id="@+id/image_checkbox_img"
  android:layout_width="100dip" 
  android:layout_height="100dip" 
  android:visibility="gone"></ImageView>
    </LinearLayout>

Edit: See the accepted answer. Lesson: Sometimes views will save and restore their state automatically. This happens AFTER onCreate. This can cause the overwriting of stuff you did in onCreate. If you don't have unique ids, all views of a certain kind (in my case textboxes) can be overwritten with the same saved state. (ps: thanks for your help everyone!)

So, I have a simple linear layout and I want to add some views that have checkboxes with images. Everything works fine until I switch the orientation of my android phone. When I do it goes back through the onCreate but this time the checkboxes all end up with the same text. Weirdly, the images appear fine.

My question is: why is it doing this and how can I make it appear like the first time everytime?

In case that makes no sense here's an example: (Edit: It turns out it always shows the last element's text)

What I see at first

[] a *a's image*
[] b *b's image*
[] c *c's image*
[] d *d's image*

Then, after rotating my phone, it redraws

[] d *a's image*
[] d *b's image*
[] d *c's image*
[] d *d's image*

My original code is pretty complex, but i constructed the following that demonstrates the problem.

Main.java:

public class Main extends Activity {

ArrayList<AnswerView> answers = new ArrayList<AnswerView>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    TextView title = (TextView)findViewById(R.id.questionText);
    title.setText("This is a test");
    HashMap<String, Drawable> answerInfo = new HashMap<String, Drawable>();
    Resources res = getResources();
    answerInfo.put("a", res.getDrawable(R.drawable.flower_orange));
    answerInfo.put("b", res.getDrawable(R.drawable.flower_white));
    answerInfo.put("c", res.getDrawable(R.drawable.leaf));
    answerInfo.put("d", res.getDrawable(R.drawable.flower_yellow));
    setBoxes(answerInfo);
}

private void setBoxes(HashMap<String, Drawable> answerInfo) {
    LinearLayout answerList = (LinearLayout)findViewById(R.id.answerlist);
    AnswerView cb = null;

    //Remove all existing answer views
    answerList.removeAllViews();
    answers.clear();

    //For each possible answer create a answer views
    for (String s : answerInfo.keySet()) {
        cb = new AnswerView(this, s, answerInfo.get(s));
        answers.add(cb);
        String text = cb.getText();
        answerList.addView(cb);
    }
}
}

AnswerView.java

 public class AnswerView extends RelativeLayout  {

private CheckBox m_checkbox;
private ImageView m_image;
//private Context m_context;

public AnswerView(Context context, String answer, Drawable d) {
    super(context);
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.image_checkbox, this, true);
    m_checkbox = (CheckBox) view.findViewById(R.id.image_checkbox_cb);
    m_image = (ImageView) view.findViewById(R.id.image_checkbox_img);
    //m_context = context;
    m_checkbox.setText(answer);
    m_image.setImageDrawable(d);
    m_image.setVisibility(VISIBLE);

}

public void setChecked(boolean checked) {
    m_checkbox.setChecked(checked);
}

public boolean isChecked() {
    return m_checkbox.isChecked();
}

public String getText() {
    return m_checkbox.getText().toString();
}

}

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
        android:layout_height="wrap_content">
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" 
  android:padding="5dip">

  <TextView android:orientation="vertical" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/questionText"
    android:textSize="18sp"/>

  <LinearLayout android:orientation="vertical" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/answerlist"/>
  <LinearLayout android:orientation="horizontal" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center">
    <Button  
    android:layout_width="200dip" 
    android:layout_height="wrap_content" 
    android:text="Enter"
    android:id="@+id/buttonAnswerEnter"/>
    />
    </LinearLayout>

</LinearLayout>
</ScrollView>

image_checkbox.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="horizontal">
  <CheckBox
   android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:id="@+id/image_checkbox_cb"></CheckBox>
  <ImageView
  android:id="@+id/image_checkbox_img"
  android:layout_width="100dip" 
  android:layout_height="100dip" 
  android:visibility="gone"></ImageView>
    </LinearLayout>

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

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

发布评论

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

评论(3

夜灵血窟げ 2024-11-13 23:30:57

为每个 AnswerView 设置唯一 ID 是否可以解决您的问题?您可以按如下方式实现:

private void setBoxes(HashMap<String, Drawable> answerInfo) {
    LinearLayout answerList = (LinearLayout)findViewById(R.id.answerlist);
    AnswerView cb = null;

    //Remove all existing answer views
    answerList.removeAllViews();
    answers.clear();

    //For each possible answer create a answer views
    // BEGIN modified code
    int counter = 0;
    // END modified code
    for (String s : answerInfo.keySet()) {
        cb = new AnswerView(this, s, answerInfo.get(s));
        // BEGIN modified code
        cb.setId(counter);
        counter++;
        // END modified code
        answers.add(cb);
        String text = cb.getText();
        answerList.addView(cb);
    }
}

Does setting a unique ID for each AnswerView solve your issue? You could achieve that as follows:

private void setBoxes(HashMap<String, Drawable> answerInfo) {
    LinearLayout answerList = (LinearLayout)findViewById(R.id.answerlist);
    AnswerView cb = null;

    //Remove all existing answer views
    answerList.removeAllViews();
    answers.clear();

    //For each possible answer create a answer views
    // BEGIN modified code
    int counter = 0;
    // END modified code
    for (String s : answerInfo.keySet()) {
        cb = new AnswerView(this, s, answerInfo.get(s));
        // BEGIN modified code
        cb.setId(counter);
        counter++;
        // END modified code
        answers.add(cb);
        String text = cb.getText();
        answerList.addView(cb);
    }
}
掩耳倾听 2024-11-13 23:30:57

实现。

onSaveInstanceState ()
onRestoreInstanceState ()

在您的自定义布局 AnswerView 中

Implement

onSaveInstanceState ()
onRestoreInstanceState ()

in your custom layout AnswerView.

动次打次papapa 2024-11-13 23:30:57

尽我所能,我无法找出为什么会发生这种情况的原因(我很乐意为任何能够解释它的人投票),但这里有一个解决方案。由于某些原因,Android 不满意您将 XML 膨胀布局调整得如此接近其在 setContentView() 中的实际膨胀。解决方案是在 onPostCreate()onResume() 中执行布局过程的动态部分,具体取决于您的 Activity 需求。

如果您负担得起,我会推荐 onResume(),因为通常不建议重写 onPostCreate()...但是 onResume()可能会经常被调用,并且可能会弄乱您的布局。以下是修改为使用 onPostCreate() 的示例。

public class Main extends Activity {

    ArrayList<AnswerView> answers = new ArrayList<AnswerView>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView title = (TextView)findViewById(R.id.questionText);
        title.setText("This is a test");
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        HashMap<String, Drawable> answerInfo = new HashMap<String, Drawable>();
        Resources res = getResources();
        answerInfo.put("a", res.getDrawable(R.drawable.flower_orange));
        answerInfo.put("b", res.getDrawable(R.drawable.flower_white));
        answerInfo.put("c", res.getDrawable(R.drawable.leaf));
        answerInfo.put("d", res.getDrawable(R.drawable.flower_yellow));
        setBoxes(answerInfo);
    }

    private void setBoxes(HashMap<String, Drawable> answerInfo) {
        LinearLayout answerList = (LinearLayout)findViewById(R.id.answerlist);
        AnswerView cb = null;

        //Remove all existing answer views
        answerList.removeAllViews();
        answers.clear();

        //For each possible answer create a answer views
        for (String s : answerInfo.keySet()) {
            cb = new AnswerView(this, s, answerInfo.get(s));
            answers.add(cb);
            String text = cb.getText();
            answerList.addView(cb);
        }
    }
}

我注意到的另外两件事可能不会影响您,但我想我会提到:

  1. 如果您希望您的项目始终以相同的顺序返回,HashMap.keySet() 是一个糟糕的选择。此方法在不同的实现中以不同的顺序返回这些值。如果您需要顺序始终相同,我会推荐 LinkedHashMapList
  2. 至少在这个例子中,在再次设置集合之前清除集合是没有意义的……因为这只有在活动被重建时才会完成。然而,在更大的实现中,这也许有更大的目的。

希望有帮助!请随意忽略任何无用的内容:)

Try as I might, I'm unable to come up with reasoning for why this is occurring (and I would happily upvote anyone who can explain it), but here is a solution. For some reason, Android isn't happy with you adjusting the XML inflated layout so close to its actual inflation in setContentView(). The solution is to do the dynamic portion of the layout process either in onPostCreate() or onResume(), depending on your Activity needs.

I would recommend onResume() if you can afford it, since onPostCreate() is not typically suggested for override...however onResume() may be called to often and may mess up your layout. Here is your example modified to use onPostCreate() instead.

public class Main extends Activity {

    ArrayList<AnswerView> answers = new ArrayList<AnswerView>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView title = (TextView)findViewById(R.id.questionText);
        title.setText("This is a test");
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        HashMap<String, Drawable> answerInfo = new HashMap<String, Drawable>();
        Resources res = getResources();
        answerInfo.put("a", res.getDrawable(R.drawable.flower_orange));
        answerInfo.put("b", res.getDrawable(R.drawable.flower_white));
        answerInfo.put("c", res.getDrawable(R.drawable.leaf));
        answerInfo.put("d", res.getDrawable(R.drawable.flower_yellow));
        setBoxes(answerInfo);
    }

    private void setBoxes(HashMap<String, Drawable> answerInfo) {
        LinearLayout answerList = (LinearLayout)findViewById(R.id.answerlist);
        AnswerView cb = null;

        //Remove all existing answer views
        answerList.removeAllViews();
        answers.clear();

        //For each possible answer create a answer views
        for (String s : answerInfo.keySet()) {
            cb = new AnswerView(this, s, answerInfo.get(s));
            answers.add(cb);
            String text = cb.getText();
            answerList.addView(cb);
        }
    }
}

Two other things I noticed which may not affect you, but I figured I'd mention:

  1. If you want your items to always return in the same order, HashMap.keySet() is a bad choice. This method returns these values in different orders on different implementations. I would recommend a LinkedHashMap or a List if you need the order to always be the same.
  2. At least in this example, it doesn't make sense to clear your collections before setting them again...since this is only done when the Activity is reconstructed anyway. In the larger implementation, however, perhaps this has a larger purpose.

Hope that Helps! Feel free to ignore anything that wasn't useful :)

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