ViewのIDが重複した場合

疑問

androidのViewはidでインスタンスとったり、どのViewか判断したりと使います。
でもOKボタンなど汎用的な名前のID名は高確率で被ります。
同じ画面でOKボタンが複数ある場合はあまり考えられませんが、異なる画面にOKボタンがあるのはあるのではないかと思います。
今回は

  • 異なる画面に同じIDのViewがあった場合
  • 同じ画面に同じIDのViewがあった場合

の2つのパターンを試したいと思います。

異なる画面に同じIDのViewがあった場合

概要説明

画面1(MainActivity)から画面2(SubActivity)に遷移します。
画面1にはEditTextとButtonが配置されており、それぞれidはtxtMessageとbtnOK
画面2にはTextViewとButtonが配置されており、それぞれidはlblResultとbtnOK
画面1と画面2のButtonのidが被ってますね
これでどうなるか見てみたいと思います。

ソースコード
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
<EditText
  android:id="@+id/txtMessage"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" />
<Button
  android:id="@+id/btnOK"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="OK" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
<TextView
  android:id="@+id/lblResult"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content"
  android:textSize="32px"
  android:text="" />
<Button
  android:id="@+id/btnOK"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="OK" />
</LinearLayout>
public class MainActivity extends Activity implements OnClickListener {
  
  private EditText txtMessage;
  private Button btnOK;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    txtMessage = (EditText)findViewById(R.id.txtMessage);
    btnOK = (Button)findViewById(R.id.btnOK);    

    btnOK.setOnClickListener(this);
  }

  @Override
  public void onClick(View v) {
    Intent i = new Intent(this,SubActivity.class);
    i.putExtra(Intent.EXTRA_TEXT, txtMessage.getText().toString());
    startActivity(i);
  }
}
  • SubActivity
public class SubActivity extends Activity implements OnClickListener {

  private TextView lblMessage;
  private Button btnOK;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sub);

    lblMessage = (TextView) findViewById(R.id.lblResult);
    btnOK = (Button) findViewById(R.id.btnOK);

    lblMessage.setText(getIntent().getExtras().getString(Intent.EXTRA_TEXT));
    btnOK.setOnClickListener(this);
  }

  @Override
  public void onClick(View v) {
    finish();
  }
}
public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int btnOK=0x7f050001;
        public static final int lblResult=0x7f050002;
        public static final int txtMessage=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
        public static final int sub=0x7f030001;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}
実行


てきとうな文字列を入れてOKボタンを押します...

無事遷移できて、最初の画面の文字列も引き継げています。
あとはOKボタンを押して最初の画面に戻れれば正常です...

無事戻ることができました。

結果

DDMSも見ていましたが、エラー・警告は出ていません。
異なる画面での同じID名の使用は、何ら問題はなさそうです。

同じ画面に同じIDのViewがあった場合

概要説明

画面1(MainActivity)から画面2(SubActivity)に遷移します。
画面1にはEditTextが2つとButtonが配置されており、それぞれidはtxtMessageとtxtMessageとbtnOK
画面2にはTextViewとButtonが配置されており、それぞれidはlblResultとbtnBack
画面1にEditTextが2つあり、それのIDが被っていますね
これでどうなるか見てみたいと思います。

ソース
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
<EditText
  android:id="@+id/txtMessage"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" />
<EditText
  android:id="@+id/txtMessage"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" />
<Button
  android:id="@+id/btnOK"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="OK" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
<TextView
  android:id="@+id/lblResult"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content"
  android:textSize="32px"
  android:text="" />
<Button
  android:id="@+id/btnBack"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="BACK" />
</LinearLayout>
public class MainActivity extends Activity implements OnClickListener {
  
  private EditText txtMessage;
  private Button btnOK;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    txtMessage = (EditText)findViewById(R.id.txtMessage);
    btnOK = (Button)findViewById(R.id.btnOK);    

    btnOK.setOnClickListener(this);
  }

  @Override
  public void onClick(View v) {
    Intent i = new Intent(this,SubActivity.class);
    i.putExtra(Intent.EXTRA_TEXT, txtMessage.getText().toString());
    startActivity(i);
  }
}
public class SubActivity extends Activity implements OnClickListener {

  private TextView lblMessage;
  private Button btnBack;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sub);

    lblMessage = (TextView) findViewById(R.id.lblResult);
    btnBack = (Button) findViewById(R.id.btnBack);

    lblMessage.setText(getIntent().getExtras().getString(Intent.EXTRA_TEXT));
    btnBack.setOnClickListener(this);
  }

  @Override
  public void onClick(View v) {
    finish();
  }
}
public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int btnBack=0x7f050003;
        public static final int btnOK=0x7f050001;
        public static final int lblResult=0x7f050002;
        public static final int txtMessage=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
        public static final int sub=0x7f030001;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}
実行


それぞれてきとうな文字列を入れてOKボタンを押します。

無事遷移ができました。

結果

私の予想ではコンパイルがそもそもできないだろうなと思っていたのですが、無事、コンパイル&実行までできちゃいました。
同じ画面で同じidを指定した場合はxmlで最初に定義したものがとられるみたいですね。
しかし2つめのEditTextの内容を取得する術はありません。少なくとも私には分かりません。
同じ画面に同じidは定義すべきではありませんね。

まとめ

異なる画面なら同じidは使ってOK
同じ画面に同じidを使うとxmlで先に書いた方が取得される

なお今回はandroid1.6とandroid2.0の両方で検証しました。

*1:自動生成

*2:自動生成