【问题标题】:Android: automatically make variables for all IDs in xmlAndroid:自动为xml中的所有ID创建变量
【发布时间】:2011-08-01 21:47:09
【问题描述】:

我注意到 Android 开发中最乏味的部分之一是布局设计,即使使用布局构建器也是如此。

设置好图形,然后布局,和布局元素做变量关联很繁琐,比如ImageButton myButton = (ImageButton)findViewById(R.id.myButton);

在较大的布局中,跟踪这些可能会变得乏味(回忆元素的名称),然后需要以任何顺序添加更多变量会令人沮丧。

为了稍微缓解这种情况,如果我在 XML 中声明的所有 ID 都自动与其适当的变量相关联,并且所有这些数据类型都已包含在该类中,那将非常方便

有什么东西已经这样做了吗?

例如,如果我写

 <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/myButton" android:id="@+id/myButton"></ImageButton>

那么我希望包含此布局的类已经拥有

 import android.ImageButton;

 ImageButton myButton;

 myButton = (ImageButton)findViewById(R.id.myButton);

这是要请求的设置还是功能?我用的是Eclipse IDE,会很方便

【问题讨论】:

  • 不是我所知道的,但会很酷 - 也许写它? :)
  • 当然,我从来没有做过自动编码监听器……我应该怎么开始? Android AVD 的那部分也会开源吗?

标签: android xml layout convenience-methods


【解决方案1】:

我制作了一个工具来自动生成用于将布局 XML 和程序逻辑绑定在一起的 Java 代码。

基本上,它采用 XML 布局,并立即为您生成所有必要的 Java 代码。支持基本成员变量、ViewHolder 模式、ArrayAdapter、CursorAdapter 和 RoboGuice 代码类型。

你可以在这里找到它:Android Layout Finder | Buzzing Android

【讨论】:

  • 感谢您发布您的答案!请务必仔细阅读FAQ on Self-Promotion。另请注意,每次链接到自己的网站/产品时,都要求发布免责声明。
  • 很棒的工具。将您的答案与 Andy 的答案结合起来并使用 @ViewById 注释生成 java 代码怎么样?可能是您工具中的一个选项,可以从 2 种方式中进行选择
  • 真是太棒了。 .....干得好,我一直在寻找它:-)
  • 这应该被接受为答案,因为这是最初询问的内容
  • 非常好的工具,感谢您与我们分享,无需使用任何第三方库即可帮助节省时间。如果您可以更新它以在使用 SDK 26 时删除视图投射,那就太好了。
【解决方案2】:

尝试使用Android Annotations。它提供了有用的注释来替换样板代码。

例如,参见@ViewById documentation:只需声明带注释的字段

@ViewById
EditText myEditText;

@ViewById(R.id.myTextView)
TextView textView;

它取代了

EditText myEditText;

TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
    [...]
    myEditText = (EditText) findViewById(R.id.myEditText);
    textView = (TextView) findViewById(R.id.myTextView);
}

【讨论】:

  • 看起来不错,但我正在使用 Xamarin Android 编程,而不是原生 Android,10 年后它似乎还没有实现:/
【解决方案3】:

自android studio version 3.6 以来,他们已经正式添加了对自动视图绑定的支持,它为每个XML 布局文件生成一个绑定类。这些类包含对在相应布局中具有 ID 的所有视图的直接引用。

您可以通过修改build.gradle 文件来启用它。

android {
  ...
  viewBinding {
      enabled = true
  }
}

如果为模块启用了视图绑定,则会为模块包含的每个 XML 布局文件生成一个绑定类。每个绑定类都包含对根视图和所有具有 ID 的视图的引用。

例如,给定一个名为result_profile.xml 的布局文件,生成的绑定类将被称为ResultProfileBinding

例子:

private ResultProfileBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ResultProfileBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
}

请查看官方文档here

【讨论】:

    【解决方案4】:

    这是一个功能请求。这是非常好的一个,我认为它会非常有用;另一方面,在某些情况下它不会很好地工作,例如,如果您正在动态膨胀视图并且在编译时不知道特定活动的哪个视图会膨胀。但是,我倾向于认为这种情况是例外而不是规则。

    最简单的方法是编写一个脚本来扫描您的布局 XML 文件以搜索具有 ID 的组件并创建具有正确定义的 .java 文件。然后,您的活动可以派生自那些自动生成的类。像这样的:

    当由您的脚本处理时,会生成一个类:

    class FooBarLayoutActivityBase extends Activity ... {
      protected ImageButton myButton;
    
      FooBarLayoutActivityBase() {
        myButton = (ImageButton)findViewById(R.id.myButton);
      }
    }
    

    然后,您可以简单地从该基类继承来使用组件...

    脚本方法很简单,不需要您深入研究工具链的代码——但您也可以直接在 ADT 插件中进行。

    【讨论】:

    • 您的代码将不起作用,因为 findViewById() 方法仅在调用 setContentView 方法后才起作用
    【解决方案5】:

    更新Android View Binding (AVB) Code Generator,这正是我要说的:|


    REGEX!

    我遇到了同样的问题,我尝试自己解决,所以我在搜索和替换亲爱的Android Studio 中变成了正则表达式。我个人使用 ButterKnife 进行带有 java 注释的依赖注入,但更重要的部分是如何自动化将 xml 布局中的 id 转换为 java 对象的过程。它有点像Android Layout Finder | Buzzing Android(该网站具有更多功能但旧:()答案但带有注释结果。

    1. 转到您的 xml 并选择带有此正则表达式 (\+id/.*) 的所有 id。 为此,首先按Ctrl + F 打开搜索面板,然后确保选中Regex 复选框。然后在框中输入正则表达式(\+id/.*),然后按Ctrl + Alt + Shift + J 选择所有匹配项。现在Ctrl + C 复制它们(你知道快捷方式)。

    例如我有这样的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutDirection="rtl"
        tools:context=".jobs.return_from_entrance.ReturnFromEntranceActivity"
        tools:ignore="HardcodedText">
    
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <GridLayout
                android:id="@+id/return_entrance_grid_layout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:columnCount="2"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="شماره برگشت" />
    
                <TextView
                    android:id="@+id/return_entrance_return_entrance_number_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="123123123"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="@string/owner_of_cargo" />
    
                <TextView
                    android:id="@+id/return_entrance_owner_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="الجی"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="تاریخ و زمان" />
    
                <TextView
                    android:id="@+id/return_entrance_time_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="12/12/12/ 12:12"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="نوع حواله" />
    
                <TextView
                    android:id="@+id/return_entrance_kind_of_order_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="حواله"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="خریدار" />
    
    
                <TextView
                    android:id="@+id/return_entrance_buyer_name_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="علی امیدی"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="مقصد" />
    
                <TextView
                    android:id="@+id/return_entrance_destination_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="آزادی"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="وزن ناخالص" />
    
                <TextView
                    android:id="@+id/return_entrance_gross_weight_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="123"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="شماره جواز" />
    
                <TextView
                    android:id="@+id/return_entrance_permission_number_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="126545643"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="شماره بارنامه" />
    
                <TextView
                    android:id="@+id/return_entrance_waybill_number_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="654"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="زمان ورود" />
    
                <TextView
                    android:id="@+id/return_entrance_enter_time_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="21/12/12 22:22"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="زمان خروج" />
    
                <TextView
                    android:id="@+id/return_entrance_exit_time_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="21/12/12 22:22"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="محوطه بارگیری" />
    
                <TextView
                    android:id="@+id/return_entrance_load_location_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="حیاط"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="نیاز به جرثقیل" />
    
                <TextView
                    android:id="@+id/return_entrance_is_crane_needed_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="ندارد"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="نیاز به لیفتراک" />
    
                <TextView
                    android:id="@+id/return_entrance_is_forklift_needed_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="ندارد"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <CheckBox
                    android:id="@+id/return_entrance_internal_return_entrance_checkbox"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="@dimen/margin_large"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginTop="@dimen/margin_large"
                    android:text="خروج داخلی" />
    
                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp" />
    
                <CheckBox
                    android:id="@+id/return_entrance_warehouse_delivery_checkbox"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="@dimen/margin_large"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginTop="@dimen/margin_large"
                    android:text="تحویل در انبار" />
    
                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp" />
    
                <Button
                    android:id="@+id/return_entrance_location_delivery_button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/margin_large"
                    android:text="تحویل در محل" />
    
                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="عکس راننده" />
    
                <ImageView
                    android:id="@+id/return_entrance_driver_image_view"
                    android:layout_width="120dp"
                    android:layout_height="120dp"
                    android:layout_gravity="center"
                    android:layout_marginTop="@dimen/item_margin"
                    android:src="@drawable/ic_account_circle_black_24dp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="@string/name_of_driver" />
    
                <TextView
                    android:id="@+id/return_entrance_name_of_driver_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="علی امیدی"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="@string/kind_of_car" />
    
                <TextView
                    android:id="@+id/return_entrance_kind_of_car_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="وانت مزدا"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="@string/plaque" />
    
                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/margin_large"
                    android:orientation="horizontal">
    
                    <TextView
                        android:id="@+id/return_entrance_plaque_2digit_text_view"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:background="@drawable/plaque_background"
                        android:padding="10dp"
                        android:text="11"
                        android:textColor="@android:color/black"
                        android:textSize="10pt"
                        android:textStyle="bold" />
    
                    <TextView
                        android:id="@+id/return_entrance_plaque_6digit_text_view"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:background="@drawable/plaque_background"
                        android:padding="10dp"
                        android:text="999ج77"
                        android:textColor="@android:color/black"
                        android:textSize="10pt"
                        android:textStyle="bold" />
                </LinearLayout>
            </GridLayout>
    
            <Button
                android:id="@+id/return_entrance_barcode_scan_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_margin="@dimen/margin_small"
                android:drawableStart="@drawable/ic_barcode"
                android:padding="@dimen/margin_medium"
                android:text="@string/scan_barcode"
                android:textSize="18sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/return_entrance_grid_layout" />
    
            <android.support.v7.widget.RecyclerView
                android:id="@+id/return_entrance_cargo_list_recycler_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/return_entrance_barcode_scan_button" />
    
            <GridLayout
                android:id="@+id/return_entrance_bottom_grid_layout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:columnCount="2"
                android:layoutDirection="rtl"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/return_entrance_cargo_list_recycler_view">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="میزان موجودی کالای قابل تحویل" />
    
                <TextView
                    android:id="@+id/return_entrance_deliverable_availability_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:text="50"
                    android:textColor="@android:color/black"
                    android:textSize="18sp" />
    
            </GridLayout>
    
            <LinearLayout
                android:id="@+id/return_entrance_bottom_linear_2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:orientation="vertical"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/return_entrance_bottom_grid_layout">
    
                <Button
                    android:id="@+id/return_entrance_cost_report_button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/margin_medium"
                    android:text="گزارش هزینه" />
    
                <Button
                    android:id="@+id/return_entrance_confirm_button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/margin_medium"
                    android:text="تایید برگشت" />
    
            </LinearLayout>
    
        </android.support.constraint.ConstraintLayout>
    </android.support.v4.widget.NestedScrollView>
    

    要填充很多文本视图,嗯?

    1. 转到您的 java 类并粘贴复制的 ID (Ctrl + V)。所以我们有一堆 id,我们想将它们更改为 java 对象。 在我们的示例中,我的 ID 是这样的:

      +id/return_entrance_grid_layout"
      +id/return_entrance_return_entrance_number_text_view"
      +id/return_entrance_owner_text_view"
      +id/return_entrance_time_text_view"
      ...
      

    是时候寻找和替换了!所以首先我们点击Ctrl + R 打开查找和替换面板。 (确保选中 REGEX 复选框) 现在我要做一些查找和替换以获得理想的结果:

    1. 查找:\+id/(.*)" 替换为:@BindView(R.id.$1) 所以我们会有这个:

      @BindView(R.id.return_entrance_grid_layout)
      @BindView(R.id.return_entrance_return_entrance_number_text_view)
      @BindView(R.id.return_entrance_owner_text_view)
      @BindView(R.id.return_entrance_time_text_view)
      ...
      

    现在是时候定义每个变量类型并命名它们了。我的 xml 命名具有 WHERE_DESCRIPTION_WHAT 模式,(something like this)。所以对于变量名,我想删除 WHERE 部分。然后定义对象type。所以我们开始吧:

    1. 查找:(@BindView\(R\.id\.return_entrance_(.*)_text_view\)) 替换为:$1 TextView $2TextView; 结果将是:

      @BindView(R.id.return_entrance_grid_layout)
      @BindView(R.id.return_entrance_return_entrance_number_text_view) TextView return_entrance_numberTextView;
      @BindView(R.id.return_entrance_owner_text_view) TextView ownerTextView;
      @BindView(R.id.return_entrance_time_text_view) TextView timeTextView;
      @BindView(R.id.return_entrance_kind_of_order_text_view) TextView kind_of_orderTextView;
      ...
      

    (只需点击Ctrl + Alt + L 即可重新格式化您的代码) 名字很丑:(。所以我们对camelCase这样做!:

    1. 查找:TextView \b(.*)_(.*) 替换为:TextView $1\u$2,结果将是:

      @BindView(R.id.return_entrance_owner_text_view)
      TextView ownerTextView;
      @BindView(R.id.return_entrance_time_text_view)
      TextView timeTextView;
      @BindView(R.id.return_entrance_kind_of_order_text_view)
      TextView kind_ofOrderTextView;
      @BindView(R.id.return_entrance_buyer_name_text_view)
      TextView buyerNameTextView;
      @BindView(R.id.return_entrance_destination_text_view)
      TextView destinationTextView;
      

    如果您重复最后一部分,任何有多个下划线的名称,每个_ 将被替换为下一个字符的大写。 所以在这个例子中,如果我再次查找:TextView \b(.*)_(.*) 替换为:TextView $1\u$2,我的TextView kind_ofOrderTextView; 将是TextView kindOfOrderTextView;

    它可能看起来有点复杂,但是当你习惯它时,它变得如此之快,它变得如此有用!例如想象在MVP 中,你有一个ModelTextViews 相同的String 名称,所以你可以这样做以使用类似的方法从Model 设置他们的所有文本。 .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 2017-09-16
      • 1970-01-01
      • 1970-01-01
      • 2012-04-23
      • 1970-01-01
      • 2021-10-06
      相关资源
      最近更新 更多