依赖库
implementation "androidx.viewpager2:viewpager2:1.0.0"
fragment基类
/**
* Fragment的基类
*
* @param <DB> data binding
* @param <VM> view model
* @author shizhiyin
*/
public abstract class BaseFragment<DB extends ViewDataBinding, VM extends BaseViewModel>
extends Fragment {
protected DB mDataBinding;
protected VM mViewModel;
private FragmentBaseBinding mFragmentBaseBinding;
private ViewLoadingBinding mViewLoadingBinding;
private ViewLoadErrorBinding mViewLoadErrorBinding;
private ViewNoNetworkBinding mViewNoNetworkBinding;
private ViewNoDataBinding mViewNoDataBinding;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
handleArguments(args);
}
initViewModel();
// ViewModel订阅生命周期事件
if (mViewModel != null) {
getLifecycle().addObserver(mViewModel);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mFragmentBaseBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_base, container, false);
mDataBinding = DataBindingUtil.inflate(inflater, getLayoutResId(),
mFragmentBaseBinding.flContentContainer, true);
bindViewModel();
mDataBinding.setLifecycleOwner(this);
initLoadState();
initCollectState();
init();
return mFragmentBaseBinding.getRoot();
}
private void initLoadState() {
if (mViewModel != null && isSupportLoad()) {
mViewModel.loadState.observe(getViewLifecycleOwner(), new Observer<LoadState>() {
@Override
public void onChanged(LoadState loadState) {
switchLoadView(loadState);
}
});
}
}
/**
* 根据加载状态 , 切换不同的View
*
* @param loadState
*/
private void switchLoadView(LoadState loadState) {
removeLoadView();
switch (loadState) {
case LOADING:
if (mViewLoadingBinding == null) {
mViewLoadingBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_loading,
mFragmentBaseBinding.flContentContainer, false);
}
mFragmentBaseBinding.flContentContainer.addView(mViewLoadingBinding.getRoot());
break;
case NO_NETWORK:
if (mViewNoNetworkBinding == null) {
mViewNoNetworkBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_network,
mFragmentBaseBinding.flContentContainer, false);
mViewNoNetworkBinding.setViewModel(mViewModel);
}
mFragmentBaseBinding.flContentContainer.addView(mViewNoNetworkBinding.getRoot());
break;
case NO_DATA:
if (mViewNoDataBinding == null) {
mViewNoDataBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_data,
mFragmentBaseBinding.flContentContainer, false);
}
mFragmentBaseBinding.flContentContainer.addView(mViewNoDataBinding.getRoot());
break;
case ERROR:
if (mViewLoadErrorBinding == null) {
mViewLoadErrorBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_load_error,
mFragmentBaseBinding.flContentContainer, false);
mViewLoadErrorBinding.setViewModel(mViewModel);
}
mFragmentBaseBinding.flContentContainer.addView(mViewLoadErrorBinding.getRoot());
break;
default:
break;
}
}
private void removeLoadView() {
int childCount = mFragmentBaseBinding.flContentContainer.getChildCount();
if (childCount > 1) {
mFragmentBaseBinding.flContentContainer.removeViews(1, childCount - 1);
}
}
@SuppressLint("FragmentLiveDataObserve")
private void initCollectState() {
if (mViewModel == null) {
return;
}
mViewModel.getCollectStatus().observe(this, new Observer<Object>() {
@Override
public void onChanged(Object collect) {
if (collect == null) {
//跳转到登录界面
LoginActivity.start(getActivity());
}
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
// ViewModel订阅生命周期事件
if (mViewModel != null) {
getLifecycle().removeObserver(mViewModel);
}
removeLoadView();
}
/**
* 处理参数
*
* @param args 参数容器
*/
protected void handleArguments(Bundle args) {
}
/**
* 是否支持页面加载。默认不支持
*
* @return true表示支持,false表示不支持
*/
protected boolean isSupportLoad() {
return false;
}
/**
* 获取当前页面的布局资源ID
*
* @return 布局资源ID
*/
protected abstract int getLayoutResId();
/**
* 初始化ViewModel
*/
protected abstract void initViewModel();
/**
* 绑定ViewModel
*/
protected abstract void bindViewModel();
/**
* 初始化
*/
protected abstract void init();
}
baseActivity
/**
* Activity的基类
*
* @param <DB> data binding
* @param <VM> view model
* @author shizhiyin
*/
public abstract class BaseActivity<DB extends ViewDataBinding, VM extends BaseViewModel>
extends AppCompatActivity {
public DB mDataBinding;
protected VM mViewModel;
private ActivityBaseBinding mActivityBaseBinding;
private ViewLoadingBinding mViewLoadingBinding;
private ViewLoadErrorBinding mViewLoadErrorBinding;
private ViewNoNetworkBinding mViewNoNetworkBinding;
private ViewNoDataBinding mViewNoDataBinding;
private BatteryReceiver receiver;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleIntent(getIntent());
if (isNoActionBar()) {
setNoActionBar();
}
mActivityBaseBinding = DataBindingUtil.setContentView(this, R.layout.activity_base);
mDataBinding = DataBindingUtil.inflate(getLayoutInflater(), getLayoutResId(),
mActivityBaseBinding.flContentContainer, true);
initViewModel();
bindViewModel();
mDataBinding.setLifecycleOwner(this);
initLoadState();
init();
//注册设备电池监听广播
receiver = new BatteryReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
BatteryManager batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
int batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
// int battery = batteryManager.getIntProperty(BatteryManager.BATTERY_STATUS_CHARGING);
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
boolean isCharging = false;
if (status == 2) {
isCharging = true;
}
handtBatteryData(batteryLevel, isCharging);
}
//wifi监测
Boolean isWifiConnected = isNetworkAvailable(context);
if (!isWifiConnected) {//没连网络
handtWifiData(false, 1);
} else {//已连网络
handtWifiData(true, 2);
}
}
};
IntentFilter filter2 = new IntentFilter();
filter2.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, filter2);
// ViewModel订阅生命周期事件
if (mViewModel != null) {
getLifecycle().addObserver(mViewModel);
}
}
/**
* 设置沉浸式状态栏
*/
private void setNoActionBar() {
Window window = getWindow();
View decorView = window.getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
}
private void initLoadState() {
if (mViewModel != null && isSupportLoad()) {
mViewModel.loadState.observe(this, new Observer<LoadState>() {
@Override
public void onChanged(LoadState loadState) {
switchLoadView(loadState);
}
});
}
}
private void removeLoadView() {
int childCount = mActivityBaseBinding.flContentContainer.getChildCount();
if (childCount > 1) {
mActivityBaseBinding.flContentContainer.removeViews(1, childCount - 1);
}
}
private void switchLoadView(LoadState loadState) {
removeLoadView();
switch (loadState) {
case LOADING:
if (mViewLoadingBinding == null) {
mViewLoadingBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_loading,
mActivityBaseBinding.flContentContainer, false);
}
mActivityBaseBinding.flContentContainer.addView(mViewLoadingBinding.getRoot());
break;
case NO_NETWORK:
if (mViewNoNetworkBinding == null) {
mViewNoNetworkBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_network,
mActivityBaseBinding.flContentContainer, false);
mViewNoNetworkBinding.setViewModel(mViewModel);
}
mActivityBaseBinding.flContentContainer.addView(mViewNoNetworkBinding.getRoot());
break;
case NO_DATA:
if (mViewNoDataBinding == null) {
mViewNoDataBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_data,
mActivityBaseBinding.flContentContainer, false);
}
mActivityBaseBinding.flContentContainer.addView(mViewNoDataBinding.getRoot());
break;
case ERROR:
if (mViewLoadErrorBinding == null) {
mViewLoadErrorBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_load_error,
mActivityBaseBinding.flContentContainer, false);
}
mActivityBaseBinding.flContentContainer.addView(mViewLoadErrorBinding.getRoot());
break;
default:
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
/**
* 电池
* 连接状态
*/
protected void handtBatteryData(int batteryLevel, boolean isCharging) {
}
/**
* wifi
* 连接状态
*/
protected void handtWifiData(boolean isConnected, int level) {
}
/**
* 处理参数
*
* @param intent 参数容器
*/
protected void handleIntent(Intent intent) {
}
/**
* 是否为沉浸模式
*
* @return true表示支持,false表示不支持
*/
protected boolean isNoActionBar() {
return false;
}
/**
* 是否支持页面加载。默认不支持
*
* @return true表示支持,false表示不支持
*/
protected boolean isSupportLoad() {
return false;
}
/**
* 获取当前页面的布局资源ID
*
* @return 布局资源ID
*/
protected abstract int getLayoutResId();
/**
* 初始化ViewModel
*/
protected abstract void initViewModel();
/**
* 绑定ViewModel
*/
protected abstract void bindViewModel();
/**
* 初始化
*/
protected abstract void init();
}
一、Fragment + TextView 实现
1、主界面
/**
* 主界面
*/
public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> {
public static void start(Context context, Boolean isLogin) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.ParamCode.PARAM1, isLogin);
context.startActivity(intent);
}
@Override
protected void handleIntent(Intent intent) {
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected int getLayoutResId() {
return R.layout.activity_main;
}
@Override
protected void initViewModel() {
mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
}
@Override
protected void bindViewModel() {
}
private List<Fragment> fragmentList;
private ContentPagerAdapter contentPagerAdapter;
@Override
protected void init() {
initView();
fragmentList = new ArrayList<>();
fragmentList.add(new HomeFragment());
fragmentList.add(new ShoppingFragment());
fragmentList.add(new LifeServicesFragment());
fragmentList.add(new EduStewarFragment());
fragmentList.add(new PersonCenterFragment());
contentPagerAdapter = new ContentPagerAdapter(this, fragmentList);
mDataBinding.viewPager.setAdapter(contentPagerAdapter);
mDataBinding.textViewHome.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(0, false));
mDataBinding.textViewShopping.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(1, false));
mDataBinding.textViewLifeServices.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(2, false));
mDataBinding.textviewEduStewar.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(3, false));
mDataBinding.textviewPersonCenter.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(4, false));
mDataBinding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 当页面滑动时调用
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
changeState(position);
}
@Override
public void onPageSelected(int position) {
// 当页面被选中时调用
super.onPageSelected(position);
}
@Override
public void onPageScrollStateChanged(int state) {
// 当页面滑动状态改变时调用
super.onPageScrollStateChanged(state);
}
});
}
/**
* 改变
* 导航栏样式
*/
private void changeState(int position) {
mDataBinding.textViewHome.setTextColor(Color.parseColor("#93A5EE"));
mDataBinding.textViewShopping.setTextColor(Color.parseColor("#93A5EE"));
mDataBinding.textViewLifeServices.setTextColor(Color.parseColor("#93A5EE"));
mDataBinding.textviewEduStewar.setTextColor(Color.parseColor("#93A5EE"));
mDataBinding.textviewPersonCenter.setTextColor(Color.parseColor("#93A5EE"));
switch (position) {
case 0:
mDataBinding.textViewHome.setTextColor(Color.parseColor("#52FDFF"));
break;
case 1:
mDataBinding.textViewShopping.setTextColor(Color.parseColor("#52FDFF"));
break;
case 2:
mDataBinding.textViewLifeServices.setTextColor(Color.parseColor("#52FDFF"));
break;
case 3:
mDataBinding.textviewEduStewar.setTextColor(Color.parseColor("#52FDFF"));
break;
case 4:
mDataBinding.textviewPersonCenter.setTextColor(Color.parseColor("#52FDFF"));
break;
default:
mDataBinding.textViewHome.setTextColor(Color.parseColor("#52FDFF"));
break;
}
}
@Override
protected void onResume() {
super.onResume();
}
/**
* 初始view
*/
private void initView() {
}
@Override
public void onBackPressed() {
// super.onBackPressed();
}
}
2、xml布局
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_640"
android:layout_height="@dimen/dp_400">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="@dimen/dp_640"
android:layout_height="350dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/bottom_navigation"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#00064F"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<TextView
android:id="@+id/textViewHome"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:text="首页"
android:textColor="#52FDFF"
android:textSize="@dimen/sp_10" />
</LinearLayout>
<TextView
android:id="@+id/textViewShopping"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:text="商城"
android:textColor="#52FDFF"
android:textSize="@dimen/sp_10" />
<TextView
android:id="@+id/textViewLifeServices"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:text="服务"
android:textColor="#52FDFF"
android:textSize="@dimen/sp_10" />
<TextView
android:id="@+id/textviewEduStewar"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:text="管家"
android:textColor="#52FDFF"
android:textSize="@dimen/sp_10" />
<TextView
android:id="@+id/textviewPersonCenter"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:text="个人"
android:textColor="#52FDFF"
android:textSize="@dimen/sp_10" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3、首页
3.1 fragment代码
public class HomeFragment extends BaseFragment<HomeFragmentLayoutBinding,HomeFragmentViewmodel> {
@Override
protected int getLayoutResId() {
return R.layout.home_fragment_layout;
}
@Override
protected void initViewModel() {
}
@Override
protected void bindViewModel() {
}
@Override
protected void init() {
}
}
3.2 布局代码
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_640"
android:layout_height="@dimen/dp_400"
android:background="@color/color_red">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="首页"
android:textColor="@color/white"
android:textSize="@dimen/sp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
4、商场页面
4.1fragment代码
public class ShoppingFragment extends BaseFragment<ShoppingFragmentLayoutBinding, ShoppingFragmentViewModel> {
@Override
protected int getLayoutResId() {
return R.layout.shopping_fragment_layout;
}
@Override
protected void initViewModel() {
}
@Override
protected void bindViewModel() {
}
@Override
protected void init() {
}
}
4.2布局代码
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_640"
android:layout_height="@dimen/dp_400"
android:background="@color/green">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="小雅购物"
android:textColor="@color/white"
android:textSize="@dimen/sp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
5、服务页面
5.1服务fragment
public class LifeServicesFragment extends BaseFragment<LifeServicesFragmentLayoutBinding, LifeServicesFragmentViewmodel> {
@Override
protected int getLayoutResId() {
return R.layout.life_services_fragment_layout;
}
@Override
protected void initViewModel() {
}
@Override
protected void bindViewModel() {
}
@Override
protected void init() {
}
}
5.2服务布局页面
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_640"
android:layout_height="@dimen/dp_400"
android:background="@color/color_red">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="生活服务"
android:textColor="@color/white"
android:textSize="@dimen/sp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
6、教育页面
6.1教育fragment代码
/**
* 教育管家
*/
public class EduStewarFragment extends BaseFragment<EduStewarFragmentLayoutBinding, EduStewarFragmentViewmodel> {
@Override
protected int getLayoutResId() {
return R.layout.edu_stewar_fragment_layout;
}
@Override
protected void initViewModel() {
}
@Override
protected void bindViewModel() {
}
@Override
protected void init() {
}
}
6.2教育布局代码
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_640"
android:layout_height="@dimen/dp_400"
android:background="@color/color_red">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="教育管家"
android:textColor="@color/white"
android:textSize="@dimen/sp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
7、个人中心
7.1个人中心fragment
public class PersonCenterFragment extends BaseFragment<PersonCenterBinding,PersonCenterVieMOdel> {
@Override
protected int getLayoutResId() {
return R.layout.person_center;
}
@Override
protected void initViewModel() {
}
@Override
protected void bindViewModel() {
}
@Override
protected void init() {
}
}
7.2个人中心布局页面
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_640"
android:layout_height="@dimen/dp_400">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="个人中心"
android:textColor="@color/black"
android:textSize="@dimen/sp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>