搭建一個簡單、易用的 Android 項目框架之BaseFragment(二)

上篇文章介紹了,我怎麼自定義一個 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();
    }
}


(2)TestActivity 的佈局文件代碼

<?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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章