讲完了网络通信模块和MVP结构。回过头来再说说基础页面的封装
BaseFragment和BaseActivity基本是一样的
在BaseActivity同级目录下新建
BaseFragment,直接贴出内容
package com.example.burro.demo.appframework.ui;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.burro.demo.appframework.mvp.presenter.BasePresenter;
import com.example.burro.demo.appframework.mvp.view.BaseView;
import com.example.burro.demo.appframework.util.StringUtils;
import com.example.burro.demo.appframework.util.ToastUtils;
import com.example.burro.demo.dataframework.model.BaseResultBean;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by ex.zhong on 2017/9/26.
* BaseFragment
* 一般使用mvp模式的话会在BaseFragment中进行P和V的初始化绑定 butterKnife的绑定 初始方法的设定
*/
public abstract class BaseFragment<T extends BasePresenter> extends Fragment implements BaseView {
protected T mPresenter;
protected FragmentActivity mContext;
private View mRootView;
private Unbinder mUnbinder;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(getLayout(), container, false);//和 BaseActivity 一样,layout() 由子类实现,提供布局。
mUnbinder = ButterKnife.bind(this, mRootView);
ButterKnife.bind(this,mRootView);
mContext = getActivity();
createPresenter();
if (mPresenter != null) mPresenter.attachView(this);
initParams();
initViews();
return mRootView;
}
protected abstract void initViews();
protected abstract void initParams();
protected abstract void createPresenter();
protected abstract int getLayout();
//统一处理错误信息
public void handleError(BaseResultBean errResult) {
if (errResult == null) return;
if (this == null) return;
//可以分门别类的处理 错误消息,如session过期,跳转到登录页面。其他情况提示即可
ToastUtils.showToast(mContext, errResult.getMsg());
}
@Override
public void onDestroyView() {
if (mPresenter != null) mPresenter.detachView();
if (mUnbinder != null) mUnbinder.unbind();
super.onDestroyView();
}
}
MainActivity,下图是大致的效果
把MainActivity贴出来的原因,是我见过好几个项目,切换做的太复杂。各种TextView的颜色设置。搞的主页面乱七八糟。这种RadioGroup+RadioButton+FrameLayout模式,先前老师也这么讲过。还有RadioGroup+RadioButton+ViewPager模式。都差不多。
主要给出MainActivity和activity_main的代码。其余部分,请到源码中查看。
package com.example.burro.demo.appbiz.main.view;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.Toast;
import com.example.burro.demo.appbiz.R;
import com.example.burro.demo.appbiz.R2;
import com.example.burro.demo.appbiz.main.MainContract;
import com.example.burro.demo.appbiz.main.MainPresenterImpl;
import com.example.burro.demo.appframework.ui.BaseActivity;
import com.example.burro.demo.appframework.util.ToastUtils;
import com.example.burro.demo.appframework.util.typeface.TypefaceUtils;
import com.example.burro.demo.dataframework.model.BaseResultBean;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.OnCheckedChanged;
/**
* Created by ex.zhong on 2017/9/27.
*/
public class MainActivity extends BaseActivity<MainPresenterImpl> implements MainContract.View {
@BindView(R2.id.toolbar)
Toolbar mToolbar;
@BindView(R2.id.rbMain0)
RadioButton rbMain0;
@BindView(R2.id.rbMain1)
RadioButton rbMain1;
@BindView(R2.id.rbMain2)
RadioButton rbMain2;
@BindView(R2.id.rbMain3)
RadioButton rbMain3;
private List mFragments;
private FragmentManager mFragmentManager;
private int currentItem = -1;
@Override
protected int initLayoutInflater() {
return R.layout.activity_main;
}
@Override
protected void initViews() {
// 继续设置字体大小
TypefaceUtils.setTextSpanAndTypeface(rbMain0, getString(R.string.icon_home) + "\n" + getString(R.string.home), 25);
TypefaceUtils.setTextSpanAndTypeface(rbMain1, getString(R.string.icon_music) + "\n" + getString(R.string.music), 25);
TypefaceUtils.setTextSpanAndTypeface(rbMain2, getString(R.string.icon_vidio) + "\n" + getString(R.string.vidio), 25);
TypefaceUtils.setTextSpanAndTypeface(rbMain3, getString(R.string.icon_mine) + "\n" + getString(R.string.mine), 25);
//设置默认选中
rbMain0.setChecked(true);
}
@Override
protected void initParams() {
//注意fragments数量和radioBtn数量要对应
mFragments = new ArrayList<>();
mFragments.add(new Fragment());
mFragments.add(new Fragment());
mFragments.add(new Fragment());
mFragments.add(new Fragment());
mFragmentManager = getSupportFragmentManager();
}
@OnCheckedChanged({R2.id.rbMain0, R2.id.rbMain1, R2.id.rbMain2, R2.id.rbMain3})
public void checkRadioBtn(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
int viewId = buttonView.getId();
if (viewId == R.id.rbMain0) {
setToolBar(mToolbar, "首页");
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
changeFragment(0);
} else if (viewId == R.id.rbMain1) {
setToolBar(mToolbar, "音乐");
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
changeFragment(1);
} else if (viewId == R.id.rbMain2) {
setToolBar(mToolbar, "视频");
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
changeFragment(2);
} else if (viewId == R.id.rbMain3) {
setToolBar(mToolbar, "我的");
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
changeFragment(3);
}
}
}
/**
* 切换fragment
*
* @param i
*/
private void changeFragment(int i) {
Log.i("TAG", "i:" + i + " currentItem:" + currentItem);
if (currentItem == i) return; //若选中的item为当前,返回
//这里不推荐使用replace()
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
if (mFragments.get(i).isAdded()) {
fragmentTransaction.hide(mFragments.get(currentItem)).show(mFragments.get(i));
} else {
if (currentItem == -1) {//初始状态新建
fragmentTransaction.add(R.id.flMain, mFragments.get(i));
} else {//非初始状态切换
fragmentTransaction.hide(mFragments.get(currentItem)).add(R.id.flMain, mFragments.get(i));
}
}
fragmentTransaction.commit();
currentItem = i;
}
@Override
protected void createPresenter() {
mPresenter = new MainPresenterImpl(this);
}
@Override
public void showError(BaseResultBean showError) {
handleError(showError);
}
long exitTime;
@Override
public void onBackPressed() {
if (rbMain0.isChecked()) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
ToastUtils.showToast(this, "再按一次将退出应用");
exitTime = System.currentTimeMillis();
} else {
super.onBackPressed();
}
} else {
rbMain0.setChecked(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Toast.makeText(MainActivity.this, "setNavigationlcon", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onMenuItemClick(MenuItem item) {
String msg = "";
msg = item.getTitle().toString();
ToastUtils.showToast(this, "您点击了" + msg);
return true;
}
}
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.base.basebiz.main.view.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/appBarLayout">
<RadioGroup
android:id="@+id/rgMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:background="@color/homeRadioBack"
>
<RadioButton
android:id="@+id/rbMain0"
android:layout_width="@dimen/dp0"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:button="@null"
android:gravity="center"
android:lineSpacingExtra="@dimen/dp3"
android:minHeight="@dimen/dp30"
android:paddingBottom="@dimen/dp5"
android:paddingTop="@dimen/dp5"
android:textColor="@drawable/selector_radiobutton_textcolor"
android:textSize="@dimen/sp12" />
<RadioButton
android:id="@+id/rbMain1"
android:layout_width="@dimen/dp0"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:button="@null"
android:gravity="center"
android:lineSpacingExtra="@dimen/dp3"
android:minHeight="@dimen/dp30"
android:paddingBottom="@dimen/dp5"
android:paddingTop="@dimen/dp5"
android:textColor="@drawable/selector_radiobutton_textcolor"
android:textSize="@dimen/sp12" />
<RadioButton
android:id="@+id/rbMain2"
android:layout_width="@dimen/dp0"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:button="@null"
android:gravity="center"
android:lineSpacingExtra="@dimen/dp3"
android:minHeight="@dimen/dp30"
android:paddingBottom="@dimen/dp5"
android:paddingTop="@dimen/dp5"
android:textColor="@drawable/selector_radiobutton_textcolor"
android:textSize="@dimen/sp12" />
<RadioButton
android:id="@+id/rbMain3"
android:layout_width="@dimen/dp0"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:button="@null"
android:gravity="center"
android:lineSpacingExtra="@dimen/dp3"
android:minHeight="@dimen/dp30"
android:paddingBottom="@dimen/dp5"
android:paddingTop="@dimen/dp5"
android:textColor="@drawable/selector_radiobutton_textcolor"
android:textSize="@dimen/sp12" />
RadioGroup>
<FrameLayout
android:id="@+id/flMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/rgMain"
android:background="@color/background">FrameLayout>
RelativeLayout>
RelativeLayout>
有两点需要强调
TextView使用字体文件不用多说,RadioButton使用字体文件却不多见。我们可以看一下RadioButton的继承关系:
一目了然,RadioButton是个特殊的TextView,适用于TextView的字体文件,当然也适用于RadioButton
这里只改变第一个字符大小
Spannable spannable = new SpannableString(text);
spannable.setSpan(new AbsoluteSizeSpan(textSize,true), 0, 1,
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
view.setText(spannable);
为什么要把ToorBar拿出来细说。细细研究了一番。不得不说安卓原生的控件的确做得很精致,而且微信也是用的原生的。
此外右侧的menu长按时还会有提示。很值得拥有,我看过好多款APP,Toolbar基本都是随意搭建的,长按没有提示不说,连点击效果没有。真是太粗糙!另外,可能大家觉得,Toolbar左侧回退和右侧menu 都是图片 这个素材有些困难。殊不知iconfont网站的任意一个字体文件都可以以png格式下载下来。
是不是顿时感叹阿里的强大!
(六)安卓框架搭建之RecyclerView和Adapter以及列表案例
github源码地址