如何设置动态创建布局的Id?

84

我希望为程序创建的布局中的一些视图(如textview,imageview等)分配ID。那么最好的设置ID的方式是什么。

10个回答

135
你需要创建一个ids.xml文件并按照以下方式将所有需要的ID放入其中。
<?xml version="1.0" encoding="utf-8"?>
<resources>
        <item type="id" name="layout1" />
        <item type="id" name="layout2" />
        <item type="id" name="layout3" />
</resources>

现在,对于您动态创建的布局或视图,您可以像下面这样使用这些id:

new_layout1.setId(R.id.layout1);
new_view2.setId(R.id.layout2);
new_layout3.setId(R.id.layout3);

希望这能对你有所帮助。


19
@Nordvind,我给亚比谢克·阿梅塔提供了一个想法,但不是完整的解决方案。他没有提到任何Android版本要求。<?xml ...>声明是基本的东西,所以任何Android开发人员都会在*.xml文件中编写。我说过它能在所有Android版本上运行吗?我的代码有什么问题吗?如果你有同样的需求,你可以使用我的答案,如果出现任何问题,请问我,不要像这样评论。 - Yugandhar Babu
1
@Nordvind 举了另一个例子,说明SO的投票系统是多么无用。可惜没有办法对评论进行踩。 - Glenn Maynard
Zaps:我在模拟器中遇到了同样的问题。你能找出问题所在吗? - IcedDante
11
这仍然没有解释如何拥有一个动态生成的 ID 集合。 - Eggcellentos
3
动态创建视图的好处在于你可能不知道需要多少或者什么时候需要它们。预先设置资源中的ID并不能起到很大的帮助。 - landrykapela
显示剩余4条评论

77

谷歌终于意识到了为编程创建的视图生成唯一ID的必要性......

从API级别17开始,可以像这样使用View.generateViewId()

view.setId(View.generateViewId());

对于目标 API 级别为 16 或更低的应用程序,请改用 ViewCompat.generateViewId()

view.setId(ViewCompat.generateViewId());

6
如果你的目标是较低的API级别,也可以使用 ViewCompat.generateViewId() - Hirbod Behnam
1
这是正确的答案,也是创建id的唯一动态方式。 - Phani Rithvij
3
我如何访问刚生成的那个ID? - Jevon

20

创建文件夹 res/values/ids.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>   
   <item name="refresh" type="id"/>   
   <item name="settings" type="id"/>        
</resources>

在 Activity 类中可以这样调用:

ImageView refreshImg = new ImageView(activity);
ImageView settingsImg = new ImageView(activity); 

     refreshImg.setId(R.id.refresh);
     settingsImg .setId(R.id.settings);

4
被问及动态创建的布局。 - Arnthor
1
创建文件夹 res/values/ids.xml 的方法是: - Bugs Happen

15

这样做是行不通的:

layout.setId(100);

但是,这样会:

int id=100;
layout.setId(id);

还有一个(摘自Aaron Dougherty):

layout.setId(100+1);

正如这里提到的,这个解决方案会生成一个编辑器验证错误(期望资源类型为id),但它可以编译成功。 - adamdport
4
实际上,如果你执行int id=100,它并没有任何问题。显然,如果你把数字加起来,它也能正常工作。不太明白为什么会有困惑。 - Mateusz Winnicki
3
谢谢@MateuszWinnicki,奇怪的是,添加数字确实有所不同。setId(100)无效,但setId(99+1)有效。 - Aaron Dougherty
@jeet,系统自动设置为100的另一个ID是否可能与ID 100发生冲突? - YoussefDir

9
为了兼容性,请使用:ViewCompat.generateViewId()

2
如果您需要以编程方式将一组组件重复放置到布局中,可以按照以下方式操作:
<LinearLayout>

      <ImageView>
      <TextView>
      <Button>

      <ImageView>
      <TextView>
      <Button>

      <ImageView>
      <TextView>
      <Button>

      ...
</LinearLayout>

然后,您可以使用for循环并相应地分配ID:
for(int i=0;i<totalGroups;i++)
{
    ImageView img;
    TextView tv;
    Button b;

    ... // set other properties of above components

    img.setId(i);
    tv.setId(i);
    b.setId(i);

    ... //handle all events on these components here only

    ... //add all components to your main layout
}

如果只想添加一个组件组,您可以使用任何大的整数编号,不会与资源中其他组件的编号冲突。这样不会有太多的冲突。


3
如何获取TextView和其他所有组件的值?请详细说明。 - Anand Savjani

1

我用了一种不同的方法。
创建了自己的R.id HashMap。
然后使用该值作为view.setID()部分的ID。
字符串是ID,整数是其值。

Private HashMap<String, Integer> idMap= new HashMap<String, Integer>();
private int getRandomId(){

    boolean notInGeneralResourses = false;
    boolean foundInIdMap = false;

    String packageName = mainActivity.getPackageName();
    Random rnd = new Random();
    String name ="";

    //Repaet loop in case random number already exists
    while(true) {

        // Step 1 - generate a random id
        int generated_id = rnd.nextInt(999999);

        // Step 2 - Check R.id
        try{
            name = mainActivity.getResources().getResourceName(generated_id);
        }catch(Exception e){
            name = null;
        }

        notInGeneralResourses = false;
        if (name == null || !name.startsWith(packageName)) {
            notInGeneralResourses = true;
        }else{
            notInGeneralResourses = false;
            localLog("Found in R.id list.");
        }

        // Step 3 - Check in id HashMap
        if(notInGeneralResourses){
            List<Integer> valueList = new ArrayList<Integer>(idMap.values());

            foundInIdMap = false;
            for (Integer value : valueList) {
                if (generated_id == value) {
                    foundInIdMap = true;
                    localLog("Found in idMAp.");
                }
            }
        }

        // Step 4 - Return ID, or loop again.
        if (!foundInIdMap) {
            localLog("ID clear for use. "+generated_id);
            return generated_id;
        }
    }
}

并设置:

 String idName = "someName";
 int generated_R_id = getRandomId();
 idMap.put(idName,generated_R_id);

 someView.setId(idMap.get(idName));

现在,您可以随时这样做:

ImageView test = (ImageView) 
mainActivity.findViewById(idMap.get("somName"));

并测试它 -

    test.setImageResource(R.drawable.differentPic);

附注:我这样写是为了方便解释。
显然,它可以更好地书写并更紧凑。


0

试试这段代码!这应该能帮助你有一个想法。

activity_prac_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

<TextView
    android:text="@string/edit_message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/display_txt"
    android:textStyle="bold"
    android:textSize="18sp"
    android:textAlignment="center"
    android:layout_gravity="center_horizontal"/>

<GridLayout
    android:id="@+id/my_grid"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:rowCount="4">


<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/linear_view">

    <Button
        android:text="@string/button_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/my_btn"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:text="@string/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/my_txt"
        android:textSize="18sp"
        />

</LinearLayout>
</GridLayout>
</LinearLayout>

这是代码的其余部分

 public class AnotherActivity extends AppCompatActivity {

private int count = 1;

List<Integer> gridArray;
private TextView myDisplayText;
@Override
protected void onCreate( Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    gridArray = new ArrayList<>();
    gridArray.add(Integer.valueOf(1));
    setContentView(R.layout.activity_prac_main);



    findViews();


}
private void findViews(){

    GridLayout gridLayout = (GridLayout)findViewById(R.id.my_grid);
    gridLayout.setColumnCount(4);
    LinearLayout linearLayout = (LinearLayout) gridLayout.findViewById(R.id.linear_view);
    linearLayout.setTag("1");
    Button myButton = (Button) linearLayout.findViewById(R.id.my_btn);
    myButton.setTag("1");
    TextView myText = (TextView) linearLayout.findViewById(R.id.my_txt);
    myText.setText("1");

    myDisplayText = (TextView) findViewById(R.id.display_txt);


    myButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            TextView txt = (TextView) view;
            myDisplayText.setText("PRESS " + txt.getTag().toString());
            if(count < 24) {

                createView();
            }
            else{
                dialogBox();
            }
        }
    });
}

private void createView(){

    LinearLayout ll = new LinearLayout(this);
    ll.setId(Integer.valueOf(R.id.new_view_id));
    ll.setTag(String.valueOf(count+1));

    Button newBtn = createButton();
    newBtn.setId(Integer.valueOf(R.id.new_btn_id));
    newBtn.setTag(String.valueOf(count+1));

    TextView txtView = createText();
    txtView.setId(Integer.valueOf(R.id.new_txt_id));
    txtView.setTag(String.valueOf(count+1));
    txtView.setText(String.valueOf(count+1));

    GridLayout gridLayout = (GridLayout)findViewById(R.id.my_grid);


   ll.addView(newBtn);
    ll.addView(txtView);
    ll.setOrientation(LinearLayout.VERTICAL);

    gridLayout.addView(ll);



        count++;

}

private Button createButton(){
    Button myBtn = new Button(this);
    myBtn.setText(R.string.button_send);
    myBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            TextView txt = (TextView) view;
            myDisplayText.setText("PRESS " + txt.getTag().toString());
            if(count < 24) {

                createView();
            }
            else{
                dialogBox();
            }
        }
    });


    return myBtn;
}
public void dialogBox() {
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
    alertDialogBuilder.setMessage("GRID IS FULL!");
    alertDialogBuilder.setPositiveButton("DELETE",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface arg0, int arg1) {
                    GridLayout gridLayout = (GridLayout)findViewById(R.id.my_grid);
                    gridLayout.removeAllViews();
                    count = 0;
                    createView();

                }
            });

    alertDialogBuilder.setNegativeButton("CANCEL",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface arg0, int arg1) {

                }
            });

    AlertDialog alertDialog = alertDialogBuilder.create();
    alertDialog.show();
}
private TextView createText(){
    TextView myTxt = new TextView(this);
    myTxt.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

    return myTxt;
}

}

正如您所看到的,ids 是在 res -> values -> ids 文件中创建的。

动态创建视图时,id 对于视图是相同的。

每个 TextView 共享相同的 id。每个 Button 共享相同的 id。每个布局共享相同的 id。

Ids 只对访问视图内容很重要。

然而,标签是使每个视图彼此独特的东西。

希望这可以帮助您!


0

你所需要做的就是调用 ViewCompat.generateViewId()

例如:

val textView = TextView(this)
textView.text = "Hello World"
textView.setLayoutParams(ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT))
textView.id = ViewCompat.generateViewId()

-1

您可以将您的ID定义为资源,然后使用视图的setId()方法来设置它。 在XML文件中,可以这样定义ID:

<resources>
  <item type="id">your id name</item>
</resources>

然后,在Java文件中使用...

layout.setId(R.id.<your id name>)

资源项引用ID必须具有名称参数,并且必须具有空的主体。 - Jose Jet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接