我注意到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,这将非常方便
答案 0 :(得分:29)
我制作了一个工具来自动生成用于将布局XML和程序逻辑绑在一起的Java代码。
基本上它需要XML布局,并立即为您生成所有必需的Java代码。支持基本成员变量,ViewHolder模式,ArrayAdapter,CursorAdapter和RoboGuice代码类型。
您可以在此处找到它:Android Layout Finder | Buzzing Android
答案 1 :(得分:15)
尝试使用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);
}
答案 2 :(得分:0)
这是一个功能请求。这是非常好的,我认为它会非常有用;另一方面,有些情况下它不能很好地工作,例如,如果您动态地膨胀视图,并且在编译时不知道特定活动将膨胀的视图。但是,我倾向于认为这种情况是例外,而不是规则。
最简单的方法是编写一个脚本,扫描布局XML文件以搜索具有ID的组件,并使用正确的定义创建.java文件。然后,您的活动可以从这些自动生成的类派生。像这样:
当您的脚本处理时,会生成一个类:
class FooBarLayoutActivityBase extends Activity ... {
protected ImageButton myButton;
FooBarLayoutActivityBase() {
myButton = (ImageButton)findViewById(R.id.myButton);
}
}
然后,您可以直接从该基类继承以使用组件...
脚本方法很简单,不需要您深入研究工具链的代码 - 但您也可以直接在ADT插件中进行操作。
答案 3 :(得分:0)
更新:Android View Binding (AVB) Code Generator,这正是我要说的:|
我遇到了同样的问题,因此我尝试自己解决该问题,因此我在搜索和替换亲爱的Android Studio
内使用了REGEX。我个人使用ButterKnife进行带有Java注释的依赖项注入,但更重要的部分是如何自动化将xml布局中的id转换为java对象的过程。有点像Android Layout Finder | Buzzing Android(该网站具有更多功能,但旧的:()答案却带有注释结果。
\+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>
要填充很多文本视图,对吧?
转到您的 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
复选框)
现在,我将进行一些查找和替换以获得理想的结果:
查找:\+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
部分。然后定义对象类型。所以我们开始:
查找:(@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
即可重新格式化代码)
名称是ulgy :(。所以我们要对camelCase!:
查找: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
中,您有一个Model
,其名称与String
的{{1}}相同,那么您可以通过此操作来从TextViews
用类似的方法...
答案 4 :(得分:0)
自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。