我无法通过其xml中布局的id到达片段的顶级',结果证明它是一个空对象。但我可以访问其子视图的父级。那个父母不是布局本身,而是“包含布局”。当我以编程方式将子项添加到此片段时,它们不会与已存在的子项对齐,建议实际上这些子项位于嵌套布局中。
这种行为真的让我感到困惑。谁能解释一下发生了什么?
我声明了一个顶级碎片布局,如下所示:
为了便于阅读而剥离了同级片段和布局设置
private void takePicture() {
openCamera();
//System.gc();
camera.startPreview();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
camera.takePicture(
new ShutterCallback() {
@Override
public void onShutter() {
// TODO Do something when the shutter closes.
}
}, new PictureCallback() {
@Override
public void onPictureTaken(byte[] _data, Camera _camera) {
}
}, new PictureCallback() {
@Override
public void onPictureTaken(byte[] _data, Camera _camera) {
// TODO Do something with the image JPEG data.
Bitmap bitmap = BitmapFactory.decodeByteArray(_data, 0, _data.length);
imgPicture.setImageBitmap(bitmap);
Toast.makeText(TakePhotoActivity.this, "Length = " + _data.length, Toast.LENGTH_SHORT).show();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "test.jpg");
// remember close de FileOutput
try {
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
CloseCamera();
}
});
}
}, 1000);
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_view"
>
<fragment
android:layout_gravity="center_horizontal|center_vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="40dp"
android:layout_weight="0.3"
android:name="foo.bar.foobar.fragments.ShowWeightsFragment"
android:id="@+id/show_weights_fragment"
tools:layout="@layout/frag_show_weights"
/>
</LinearLayout>
定义如下:
layout/frag_show_weights
MainActivity.java如下所示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_container_weights"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Foo"
android:id="@+id/xmlTextChildren"
android:layout_gravity="center" />
</LinearLayout>
日志输出如下:
08-22 12:06:24.855:D / MainActivity(2346):ID的布局为空
08-22 12:06:24.856:D / MainActivity(2346):ID父名:show_weights_fragment
实际的模拟器输出显示两个文本没有对齐,这使我假设它们不包含在同一个protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t = (TextView) findViewById(R.id.xmlTextChildren);
t.setText("Foo");
LinearLayout parentLayout = (LinearLayout) findViewById(R.id.xmlTextChildren).getParent();
LinearLayout layoutFromID = (LinearLayout) findViewById(R.id.layout_container_weights);
TextView v = new TextView(this);
v.setText("Bar");
if (layoutFromID == null) Log.d(TAG, "Layout from ID is null");
Log.d(TAG, "ID parent name: " + getResources().getResourceEntryName(parentLayout.getId()));
parentLayout.addView(v);
}
中
答案 0 :(得分:2)
简答:如果您在R.id.show_weights_fragment
内设置了ID,请使用您的片段的ID <fragment>
来访问其视图。
The documentation for Fragments有一个关于片段处理ID的声明:
注意:每个片段都需要一个唯一的标识符,如果重新启动活动,系统可以使用该标识符来恢复片段(您可以使用它来捕获片段以执行事务,例如删除它)。有三种方法可以为片段提供ID:
- 使用唯一ID提供android:id属性。
- 使用唯一字符串提供android:tag属性。
- 如果您不提供前两个,系统将使用容器视图的ID。
如果设置了片段的id,这就会激发假设,即它只是反过来。我无法找到关于此的文档,但是the sources for FragmentManagerImpl
表明,这个假设成立:
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
return null;
}
[...]
int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
[...]
if (id != 0) {
fragment.mView.setId(id);
}
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
return fragment.mView;
}
这也是您的日志显示的内容:parentLayout.getId() == R.id.show_weights_fragment
。
答案 1 :(得分:0)
尝试将代码从onCreate移动到onCreateView。
来自Android doc:
“使用getSystemService(Class)返回的LayoutInflater进行充气时使用的onCreateView(View,String,Context,AttributeSet)的标准实现。此实现处理标记以在活动中嵌入片段。”