bry*_*yan 2 android android-fragments
我遇到了一个问题,即片段的根 ID 在被活动扩展时会发生变化。我能够解决这个问题,但我试图弄清楚是否应该始终避免将 ID 放在根视图上,以便在用户通过 XML 将其附加到活动的情况下不会重命名.
这是我的activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment"
android:name="com.example.fragmenttest.MainActivityFragment"
tools:layout="@layout/fragment_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Run Code Online (Sandbox Code Playgroud)
这是我的 fragment_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mylayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivityFragment">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
现在,如果我想在片段的 onCreateView 期间引用 RelativeLayout,我可以调用 findViewById(R.id.mylayout) 并且它可以工作。但是,如果我稍后调用它,则无法使用
rl = getView().findViewById(R.id.mylayout);
Run Code Online (Sandbox Code Playgroud)
因为根视图的 ID 已更改为 R.id.fragment(我可以使用它来获取 RelativeLayout)。
所以我想知道我是否应该设置片段根视图的 ID,以防下一个开发人员直接在 XML 中使用它。
主要活动:
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
MainActivityFragment fragment = (MainActivityFragment) getSupportFragmentManager()
.findFragmentById(R.id.fragment);
fragment.doIdTest();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Run Code Online (Sandbox Code Playgroud)
和 MainActivityFragment:
public class MainActivityFragment extends Fragment {
public MainActivityFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
public void doIdTest() {
View rl = getView().findViewById(R.id.mylayout);
if (rl == null) {
Log.wtf("Ack!", "Can't find the RelativeLayout!");
}
rl = getView().findViewById(R.id.fragment);
if (rl != null && rl instanceof RelativeLayout) {
Log.wtf("Ack!", "ID of the relative layout is fragment!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以在此处查看演示该问题的完整项目:https : //www.dropbox.com/s/08xu4bxi84rsms3/FragmentTest.tar.gz?dl=0
我试过你的代码,恐怕我看到的东西和你一样 - Idrootview 的RelativeLayout实际上是从R.id.myLayout到R.id.fragment. :O
我做了一点挖掘,发现在Activity#setContentView它内部实际上调用了FragmentManager,作为回报,它将调用所有Fragment添加到Activity. 然后FragmentManager#onCreateView在被调用时Fragment#onCreateView被调用。
当Fragment#onCreateView被称为随后的的rootviewFragment仍然是R.id.myLayout,但之后FragmentManager#onCreateView一直呼吁,由于某种原因,这种方法改变了Id的mView和mInnerView的Fragment在这部分代码:
if (id != 0) {
fragment.mView.setId(id);
}
Run Code Online (Sandbox Code Playgroud)
此时fragment.mView已经有了Id一套—— R.id.myLayout.
代码中没有解释为什么会发生这种情况以及为什么需要它,但事实是它会发生。
作为参考,这里是该方法的PastebinFragmentManager#onCreateView。
现在我要做的就是忘记Id R.id.myLayout你的RelativeLayout。
您将始终能够RelativeLayout通过这样做从Activity例如:
MainActivityFragment fragment = (MainActivityFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
RelativeLayout rootView = (RelativeLayout) fragment.getView();
Run Code Online (Sandbox Code Playgroud)
在getView将始终返回rootview,它可以转换的RelativeLayout。这并不漂亮,但我认为它应该是这样工作的。
如果您想获得RelativeLayout来自内部的Fragment,只需要调用getView直接丢在一个RelativeLayout或作出一个全局变量里面的rootview Fragment-这至少是我们在我的工作做在我们的代码:-)
此外,如果您删除Id的Fragment内部activity_main.xml的FragmentManager#onCreateView还是会覆盖当前Id你的RelativeLayout,你将无法使用View#findViewById依然。
至于为什么谷歌会覆盖这个Id我无法回答,但Fragment在我看来整个系统有点不稳定。
我希望这至少能说明实际发生的事情:-)
| 归档时间: |
|
| 查看次数: |
1987 次 |
| 最近记录: |