上篇文章介紹了,我怎麼自定義一個 BaseActivity ,自然是少不了BaseFragment 了。
不多廢話,直接上代碼了啦!
public abstract class TBaseFragment extends Fragment implements View.OnClickListener {
protected Context mContext;//上下文
protected View contentView;//parentView
private int layoutResId;//佈局 id
private Toast toast;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mContext = getActivity();
toast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT);
if (contentView == null) {
contentView = inflater.inflate(layoutResId, container, false);
}
ViewGroup parent = (ViewGroup) contentView.getParent();
if (parent != null) {
parent.removeView(contentView);
}
initViewAfterOnCreate();
initDataAfterOnCreate();
return contentView;
}
public void setContentLayout(int layoutResId) {
this.layoutResId = layoutResId;
}
protected <T> T $(int id) {
T view = (T) contentView.findViewById(id);
return view;
}
protected void showToast(String str) {
if (!TextUtils.isEmpty(str)) {
toast.setText(str);
toast.show();
}
}
protected void showToast(int strId) {
showToast(getString(strId));
}
protected void registerOnClickListener(TBaseFragment fragment, View... views) {//註冊點擊事件
for (View view : views) {
view.setOnClickListener(fragment);
}
}
@Override
public void onClick(View v) {
}
/**
* 用於從xml文件中inflate控件View
*/
public abstract void initViewAfterOnCreate();
/**
* 給View填充數據
*/
public abstract void initDataAfterOnCreate();
}
注:(1)BaseFragment 的實現跟BaseActivity 的實現類似,不過,增加了自定義方法 setContentLayout() 用於傳遞佈局的資源 id 到基類,通過這種方式,可以使用 Fragment 的子類的實現跟 Activity 的實現近乎一致,可以保持代碼有較強的可讀性
(2)protected<T> T $(int id) 方法的實現,藉助 contentView 實現了 findViewById 與分離 onCreateView 的關係分離(否則,findViewById 需要依賴 onCreateView 創建的 View 來實現)
下面是一個簡單的頁面包含標題欄,返回按鈕(及相應關閉事件),Activity界面內嵌一個 TestFragment,Fragment 頁面裏面只有一個“點擊我,展示 Toast”的按鈕(點擊展示 Toast信息)
(1)TestActivity 頁面 java代碼
public class TestActivity extends TBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.act_test);
super.onCreate(savedInstanceState);
}
@Override
public void initViewAfterOnCreate() {
backWithTitle("測試標題");
}
@Override
public void initDataAfterOnCreate() {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout, new TestFragment()).commitAllowingStateLoss();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<include layout="@layout/title_bar"/>
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
(3)TestFragment java 代碼
public class TestFragment extends TBaseFragment {
private TextView tv_test;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
setContentLayout(R.layout.frag_test);
super.onCreate(savedInstanceState);
}
@Override
public void initViewAfterOnCreate() {
tv_test = $(R.id.tv_test);
registerOnClickListener(this, tv_test);//註冊點擊事件
}
@Override
public void initDataAfterOnCreate() {
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_test://點擊按鈕
showToast(tv_test.getText().toString());
break;
}
super.onClick(v);
}
}
注:可以發現 TestFragment 的的方法的實現跟 Activity 實現幾乎一致,唯一的區別就是在 onCreate 方法裏面調用了一個自定義的 setContentLayout 方法設置當前 Fragment 的佈局文件
(4)TestFragment 佈局文件代碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:text="點擊我,展示 Toast"
android:textSize="20dp"/>
</LinearLayout>
截止目前介紹了 BaseFragment 的實現及應用,通過這種方式有兩個優點
(1)使 Fragment 與普通的 Activity 保持一致的方法模式,代碼更簡潔易懂
(2)實現了 findViewById 與 onCreateView 方法的關係分離,同時民使用 findViewById 的調用更加簡潔。
Demo GitHub 地址:https://github.com/chende008/TestProject