我有以下布局设置(我省略了不相关的标签):
main.xml:
<include
android:id="@+id/test1"
layout="@layout/mylayout"
/>
<include
android:id="@+id/test2"
layout="@layout/mylayout"
/>
mylayout.xml:
<LinearLayout
<EditText
android:id="@+id/myedittext"
/>
</LinearLayout>
请注意,此特定示例至关重要过度简化,我的实际mylayout.xml
很复杂,并且包含大量带有大量ID的子布局和子视图,我会真的不喜欢将其内联到main.xml
。
所以,我想多次重复使用布局mylayout.xml
。您可能会注意到两个EditTexts将具有重复的ID。这似乎不是问题,因为我只在活动初始化时使用R.id.myedittext
来查找test1
或test2
布局为findViewById
的根的视图,之后我直接通过View对象访问这些EditTexts。我发现Butterknife非常方便,代码看起来像这样:
class LayoutHolder {
@InjectView(R.id.myedittext)
EditText editText;
// ...
static LayoutHolder create(View root) {
LayoutHolder holder = new LayoutHolder();
ButterKnife.inject(holder, root);
return holder;
}
}
当我尝试更改屏幕方向时出现问题:由于这些非唯一ID,两个EditTexts都恢复了相同的状态。好吧,我想,我只需要在values
目录中定义一些ID,然后在EditTexts上使用View.setId
方法。但是这种方法存在一些问题:特别是,我必须为mylayout.xml
内的ID的每个视图手动和编程设置这些ID。更重要的是,即使我这样做,我也不能再以统一的方式访问这些子视图,因为它们都会有不同的ID(特别是,我不能做这些不错的Butterknife注射)
我已经找到了解决这个问题的其他方法,但它们更加复杂和丑陋。那么,是否有一些很好的通用方法来满足我的需求呢?我不知道我在网上找不到任何东西,因为重复使用布局以避免代码重复(实际上是xml复制,但无论如何)看起来很自然。
答案 0 :(得分:0)
我一直在使用我在开源项目中找到的代码。
public class Utils {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
/**
* Generate a value suitable for use in setId(int}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* @return a generated ID value
*/
private static int generateViewId() {
for (; ; ) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) {
newValue = 1; // Roll over to 1, not 0.
}
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
@SuppressLint("NewApi")
public static int generateId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return generateViewId();
}
else {
return View.generateViewId();
}
}
}
答案 1 :(得分:0)
修补黄油刀,所以它会支持两个这样的ID
@InjectView(R.id.mylayout, R.id.myedittext)