第一行代码读书笔记
碎片
- 碎片是一种考验嵌入活动中的UI片段
- 在平板上广泛应用
基础使用
-
新建两个碎片
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Button" /> </LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="#00ff00" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp" android:text="This is a right fragment" /> </LinearLayout>
-
新建LeftFragmetn类,继承自Fragment
public class LeftFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.left_fragment, container, false); return view; } }
- support-v4库中的Fragment支持版本兼容 android.support.v4.app.Fragment
- 重写onCreateView()方法,通过LayoutInflater的inflate()方法将left_fragment布局动态加载进来
-
同理新建RightFragment类
public class RightFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
}
- 修改activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/lft_fragment" android:name="com.example.fragmenttest.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/right_fragment" android:name="com.example.fragmenttest.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>
- 使用
<fragment>
标签 android:name
- 显式指明要添加的碎片类名
- 类的包名也要加上
- 使用
动态添加碎片
- 新建another_right_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="#ffff00" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp" android:text="This is another right fragment" /> </LinearLayout>
- 新建AnotherRightFragment类
public class AnotherRightFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.another_right_fragment, container, false); return view; } }
- 修改activity_main.xml,将right_fragment替换为
<FrameLayout android:id="@+id/right_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" />
- 修改MainActivity,向FrameLayout添加内容
public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(this); replaceFragment(new RightFragment()); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: replaceFragment(new AnotherRightFragment()); break; default: break; } } private void replaceFragment(Fragment fragment) { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.replace(R.id.right_layout, fragment); transaction.commit(); } }
- 动态添加碎片主要分为5步
- 创建待添加的碎片实例
- 获取
FragmentManager
,在活动中可以直接通过调用getSupportFragmentManager()
的方式得到 - 开启一个事务
FragmentTransaction
,通过调用beginTransaction()
方法开启 - 向容器内添加或替换碎片,一般使用
replace()
方法实现,需要传入容器的id
和待添加的碎片实例 - 提交事务,调用
commit()
方法完成
在碎片中模拟返回栈
FragmentTransaction
中提供了addToBackStack()
方法private void replaceFragment(Fragment fragment) { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.replace(R.id.right_layout, fragment); transaction.addToBackStack(null); transaction.commit(); }
- 用于将事务添加到返回栈中
- 接收一个名字用于描述返回栈的状态
一般传入null
碎片和活动之间通信
FragmentTransaction
中提供了findFragmentById()
方法RightFragment rightFragment = (RightFragment) getFragmentManager() .findFragmentById(R.id.right_fragment);
- 用于从布局文件中获取碎片的实例
getActivity()
MainActivity activity = (MainActivity) getActivity();
- 用于获取和当前碎片相关联的活动实例
- 当碎片中需要使用
Context
对象时也可以使用
获取到的活动本身就是Context对象
碎片的生命周期
碎片的状态和回调
- 运行状态
- 可见的,并且它所关联的活动正处于运行状态
- 暂停状态
- 当一个活动进入暂停状态,与它关联的可见碎片就会进入暂停状态
- 停止状态
- 当一个活动进入停止状态,与它关联的碎片就会进入停止状态
- 通过调用FragmentTransaction的
remove()
、replace()
方法将碎片从活动中移除,
但在事务提交前调用addToBackStack()
方法,该碎片进入停止状态 - 完全不可见的,有可能被系统回收
- 销毁状态
- 当活动被销毁时,与它关联的碎片就会进入销毁状态
- 通过调用FragmentTransaction的
remove()
、replace()
方法将碎片从活动中移除,
但在事务提交前没有调用addToBackStack()
方法,该碎片进入销毁状态
onAttach()
:当碎片和活动建立关联时调用
onCreateView()
:为碎片创建视图(加载布局)时调用
onActivityCreated()
:确保与碎片关联的活动一定已经创建完毕时调用
onDestroyView()
:当与碎片关联的视图被移除时调用
onDetacch()
:当碎片和活动解除关联时调用- 碎片的完整生命周期
-> onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() -> onResume() -> 碎片激活
(移除)
-> onPause() -> onStop() -> onDestroyView()(如果是返回栈中的碎片,回到上一个碎片onCreateView())-> onDestroy() -> onDetach()
动态加载布局的技巧
限定符
- Quilifier
- 在res目录下新建layout-large文件夹
屏幕被认为是large的设备就会自动加载layout-large文件夹下的布局 - 大小
- small, normal, large, xlarge
- 分辨率
- ldpi, mdpi, hdpi, xhdpi, xxhdpi
- 方向
- land(横屏), port(竖屏)
最小宽度限定符
- Smallest-width Qualifier
- dp为单位
- E.g. 新建文件夹layout-sw600d