21

我注意到 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,它会非常方便

4

5 回答 5

35

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

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

你可以在这里找到它:Android Layout Finder | 嗡嗡的安卓

于 2013-02-15T14:17:40.850 回答
15

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

例如,请参阅@ViewById 文档:只需声明带注释的字段

@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);
}
于 2011-08-02T19:44:57.803 回答
2

从android studio 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);
}

请在此处查看官方文档。

于 2020-03-02T15:30:58.060 回答
0

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

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

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

class FooBarLayoutActivityBase extends Activity ... {
  protected ImageButton myButton;

  FooBarLayoutActivityBase() {
    myButton = (ImageButton)findViewById(R.id.myButton);
  }
}

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

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

于 2011-08-02T04:14:24.850 回答
0

更新Android 视图绑定 (AVB) 代码生成器,这正是我要说的:|


正则表达式!

我有同样的问题,我试图自己解决它,所以我在搜索和替换中变成了 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类并粘贴复制的 ids( 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. Find : \+id/(.*)"Replace with:@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模式,(像这样)。所以对于变量名,我想删除该WHERE部分。然后定义对象类型。所以我们开始:

  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;
    ...
    

(只需点击 aCtrl + Alt + L重新格式化您的代码)名称是 ulgy :( 。所以我们对 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$2TextView kind_ofOrderTextView;将是TextView kindOfOrderTextView;

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

于 2018-07-30T11:39:17.817 回答