学习笔记
0. 分析 Activity 与 Fragment 的区别,部分使用的差异
上一篇中我们分析了Activity 与 Fragment 的区别,部分使用的差异。
1. 单个 Activity
中使用多个 Fragment
这是最常见的用法之一,特别是在单屏幕应用中。通过在一个 Activity
中加载多个 Fragment
,你可以将 UI 划分为不同的模块,每个 Fragment
负责自己的布局和逻辑。
使用场景:
- 多页面布局的单屏应用(如多个选项卡、分步表单等)
- 侧边菜单、导航栏等界面设计
示例:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 加载第一个 Fragment
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new FragmentA());
transaction.commit();
}
}
}
在布局文件 activity_main.xml
中,使用一个容器 FrameLayout
来承载多个 Fragment
:
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Fragment 示例:
public class FragmentA extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
}
2. Tab 布局中的 Fragment
当你需要在 Activity
中实现多个选项卡(tab)页面时,TabLayout
与 ViewPager
配合使用是常见的方式。每个选项卡对应一个 Fragment
,并通过 ViewPager
进行滑动切换。
使用场景:
- 新闻应用、社交媒体应用的首页。
- 购物应用中的“首页”、“推荐”、“购物车”选项卡。
示例:
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.viewPager);
tabLayout = findViewById(R.id.tabLayout);
// 配置 ViewPager 和 TabLayout
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FragmentA(), "Tab 1");
adapter.addFragment(new FragmentB(), "Tab 2");
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
public class ViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList = new ArrayList<>();
private List<String> titleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
titleList.add(title);
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
@Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
}
}
3. 主界面和详情界面的 Fragment 设计
在许多应用中,主界面展示一个列表(如新闻列表、商品列表),当用户点击某个条目时,会跳转到该条目的详情页面。这种场景下,Fragment
的使用可以极大简化界面设计,并且实现灵活的页面切换。
使用场景:
- 商品详情页面
- 新闻详细页面
示例:
在 MainActivity
中展示一个列表,点击列表项后展示详情页:
public class MainActivity extends AppCompatActivity implements OnItemClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化 RecyclerView 等
}
@Override
public void onItemClick(Item item) {
// 列表项点击后,切换到详情 Fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, ItemDetailFragment.newInstance(item));
transaction.addToBackStack(null); // 加入返回栈
transaction.commit();
}
}
在 ItemDetailFragment
中显示详细内容:
public class ItemDetailFragment extends Fragment {
private static final String ARG_ITEM = "item";
public static ItemDetailFragment newInstance(Item item) {
ItemDetailFragment fragment = new ItemDetailFragment();
Bundle args = new Bundle();
args.putSerializable(ARG_ITEM, item);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);
// 获取传递的 Item 对象并显示
Item item = (Item) getArguments().getSerializable(ARG_ITEM);
// 显示详情
return rootView;
}
}
4. 侧滑菜单与 Fragment 结合使用
通过 DrawerLayout
可以实现应用中的侧滑菜单,侧滑菜单通常由一个 Fragment
组成,可以在主 Activity
中动态切换显示。
使用场景:
- 应用中的侧边栏菜单
- 设置页面等
示例:
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
private ActionBarDrawerToggle toggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawerLayout = findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(this, drawerLayout,
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
// 加载侧边栏 Fragment
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new SideMenuFragment())
.commit();
}
}
在侧边栏 SideMenuFragment
中处理点击事件,动态切换主界面内容。
5. 处理屏幕旋转或配置变化时的 Fragment
状态保存
在 Android 中,屏幕旋转或配置变化(如语言更改)时,Activity
会被销毁并重新创建。如果你在 Activity
中加载了 Fragment
,这些 Fragment
可能会被销毁。为避免重新加载或丢失数据,你可以通过 onSaveInstanceState()
和 onViewStateRestored()
来保存和恢复 Fragment
的状态。
使用场景:
- 保持列表滚动位置
- 防止屏幕旋转导致的数据丢失
示例:
在 Fragment
中保存和恢复状态:
public class MyFragment extends Fragment {
private static final String KEY_POSITION = "position";
private int position;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
position = savedInstanceState.getInt(KEY_POSITION, 0);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_POSITION, position);
}
// 在 onCreateView 中恢复滚动位置或其他状态
}
6. 支持多种屏幕大小的设计:Tab 变为列表
在平板和手机设备上,Fragment
可以用来支持不同的布局。例如,在平板上显示 Tab
或多个 Fragment
,而在手机上则使用列表和细节页面的单列布局。
使用场景:
- 平板和手机设备上不同的布局(响应式设计)
- 主屏幕在小屏设备上以列表显示,在大屏设备上显示多个
Fragment
示例:
在 MainActivity
中根据设备的大小来决定显示的布局:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
// 在平板设备上加载两个 Fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new FragmentA());
transaction.replace(R.id.fragment_container_2, new FragmentB());
transaction.commit();
} else {
// 在手机设备上加载一个 Fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new FragmentA());
transaction.commit();
}
}
}
总结
这些是 Activity
和 Fragment
在 Android 开发中的常见使用案例。Fragment
作为一个灵活的 UI 组件,可以帮助开发者在应用中实现更加模块化、灵活的界面设计,并能够有效地支持不同的屏幕尺寸、设备方向等配置变化。通过合理的组合和管理,可以大大提升应用的用户体验和性能。