一般來說,項目中都會有多個Activity或者Fragment,每個界面都會有一些相同的地方,比如標題欄、無數據界面、網絡錯誤界面,每個界面都寫就會顯得很重複,也不便於維護。所以這個時候就有必要寫一個基類來進行封裝,也就是BaseActivity或者BaseFragment
先看一下效果
無數據和網絡錯誤的情況。對於上邊的標題欄,可能有多種情況,有標題欄,無標題欄,是否有返回按鈕,右邊是否顯示文字或圖片。這些情況我們都可以寫在基類中。這些公用的界面都是寫在BaseActivity的對應的xml文件中。
activity_base.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_base_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
>
<include
android:id="@+id/activity_base_title_bar"
layout="@layout/title_bar" />
<include
android:id="@+id/activity_base_state_layout"
android:visibility="gone"
layout="@layout/state_layout"/>
</LinearLayout>
裏面用include添加進兩個佈局title_bar就是標題欄,state_layout是無數據和無網絡的佈局。
title_bar.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/x100"
android:background="@color/colorPrimaryDark">
<TextView
android:id="@+id/title_bart_tv_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="返回"
android:drawableLeft="@drawable/icon_back_small"
android:drawablePadding="@dimen/x6"
android:textColor="@color/colorBlack"
android:layout_marginLeft="@dimen/x20"
android:textStyle="bold"
android:textSize="@dimen/bigOneSize" />
<TextView
android:id="@+id/title_bart_tv_middle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginLeft="@dimen/x20"
android:text=""
android:textColor="@color/colorBlack"
android:textSize="@dimen/bigTwoSize"
android:textStyle="bold" />
<TextView
android:id="@+id/title_bart_tv_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="@dimen/x20"
android:layout_centerVertical="true"
android:text=""/>
</RelativeLayout>
state_layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/state_layout_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_error" />
<Button
android:id="@+id/state_layout_error_bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="網絡異常,點擊重新加載"
android:textColor="@drawable/text_primary_light_selector" />
</LinearLayout>
<LinearLayout
android:id="@+id/state_layout_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_empty" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="暫無數據"
android:textColor="@color/colorGrayText" />
</LinearLayout>
</RelativeLayout>
兩個佈局就不多說了,主要看BaseActivity的代碼
public class BaseActivity extends AppCompatActivity {
LinearLayout mRootBaseView;//根佈局
View titleView;//include的titleBar
TextView tvLeft;//titleBar左邊的返回鍵
TextView tvMiddle;//titleBar的標題
View mStateLayout;//include的state_layout
LinearLayout ll_page_state_error;//stateLayout網絡錯誤的佈局
LinearLayout ll_page_state_empty;//stateLayout無數據的佈局
Button btReload;//網絡錯誤重新加載的佈局
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_base);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
initBaseView();
/*//5.0以下設置狀態欄顏色
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
new SystemStatusManager(this).setTranslucentStatus(R.color.colorPrimaryDark);
getWindow().getDecorView()
.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}*/
}
//這裏控件初始化沒用ButterKnife 會報錯 原因暫時沒找到
public void initBaseView() {
mRootBaseView = (LinearLayout) findViewById(R.id.activity_base_root);
titleView = findViewById(R.id.activity_base_title_bar);
tvLeft = (TextView) findViewById(R.id.title_bart_tv_left);
tvMiddle = (TextView) findViewById(R.id.title_bart_tv_middle);
mStateLayout = findViewById(R.id.activity_base_state_layout);
btReload = (Button) findViewById(R.id.state_layout_error_bt);
ll_page_state_empty = (LinearLayout) findViewById(R.id.state_layout_empty);
ll_page_state_error = (LinearLayout) findViewById(R.id.state_layout_error);
}
/**
* 必須重寫setContentView注意不能夠添加這行代碼 目的將當前界面的佈局添加到BaseActivity中去
* super.setContentView(R.layout.activity_base);
*/
@Override
public void setContentView(int layoutResID) {
View view = getLayoutInflater().inflate(layoutResID, null);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
if (null != mRootBaseView) {
mRootBaseView.addView(view, lp);
}
}
/**
*
* @param titleBarIsShow titleBar是否顯示
* @param tvLeftIsShow 返回鍵是否顯示
* @param middleText 中間的文字
*/
public void initTitleBar(boolean titleBarIsShow, boolean tvLeftIsShow,
String middleText) {
if (titleBarIsShow == true) {
if (!tvLeftIsShow) {
tvLeft.setVisibility(View.GONE);
} else {
tvLeft.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
tvMiddle.setText(middleText);
} else {
titleView.setVisibility(View.GONE);
}
}
/**
* 切換頁面的佈局
* @param pageState 頁面狀態 NORMAL EMPTY ERROR
*/
public void changePageState(PageState pageState) {
switch (pageState) {
case NORMAL:
if (mStateLayout.getVisibility() == View.VISIBLE) {
mStateLayout.setVisibility(View.GONE);
}
break;
case ERROR:
if (mStateLayout.getVisibility() == View.GONE) {
mStateLayout.setVisibility(View.VISIBLE);
ll_page_state_error.setVisibility(View.VISIBLE);
btReload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
reloadInterface.reloadClickListener();
}
});
ll_page_state_empty.setVisibility(View.GONE);
}
break;
case EMPTY:
if (mStateLayout.getVisibility() == View.GONE) {
mStateLayout.setVisibility(View.VISIBLE);
ll_page_state_error.setVisibility(View.GONE);
ll_page_state_empty.setVisibility(View.VISIBLE);
}
break;
}
}
//網絡錯誤重新加載的接口
public ReloadInterface reloadInterface;
public void setReloadInterface(ReloadInterface reloadInterface) {
this.reloadInterface = reloadInterface;
}
public interface ReloadInterface {
void reloadClickListener();
}
public enum PageState {
/**
* 數據內容顯示正常
*/
NORMAL,
/**
* 數據爲空
*/
EMPTY,
/**
* 數據加載失敗
*/
ERROR
}
}
在MyMessageActivity繼承BaseActivity並實現ReloadInterface接口,如果該界面沒有用到則不用實現此接口
public class MyMessageActivity extends BaseActivity implements ReloadInterface {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_message);//重載BaseActivity的setContentView方法
initTitleBar(true, true, "我的消息");
setReloadInterface(this);
}
@Override
public void reloadClickListener() {
//You want to do
}
}
對於佈局的切換,主要是在網絡請求裏調用,比如OkHttp在請求失敗的時候調用changePageState(PageState.Error);
okHttpHelper.post(Constants.HTTP.BaseUrl, params, new ProgressDialogCallBack<MessageEntity>(context) {
@Override
public void onFailure(Request request, IOException e) {
changePageState(PageState.ERROR);//切換成網絡異常佈局
}
@Override
public void onSuccess(Response response, MessageEntity messageEntity) {
List<List> messageList = messageEntity.getMsg().getRows();
if (messageList.size() == 0) {//數據爲空顯示無數據
changePageState(PageState.EMPTY);
}else{//數據不爲空正常顯示
changePageState(PageState.NORMAL);
}
}
});
如果後期項目需要,還會繼續更新BaseActivity。
明天就是端午節了,大家端午節快樂!