前一篇已经将SplashActivity编写好了,这篇主要梳理一下主页面MainActivity。包括:
一般项目开发中,会涉及到很多的Activity和Fragment的使用,而且我们在这些activity或者fragment中操作的方法大致一样:初始化view,初始化data,初始化listener,以及实现一些控件的onClick方法。
所以为了方便,我们将这些方法向上抽取,放到一个BaseActivity以及一个BaseFragment当中去。当需要使用的时候,直接继承我们已经写好的这些基类,这样,不仅少了不少重复代码,而且可读性极大增强,逻辑更加清晰。
public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initViews();
initData();
initListeners();
}
protected abstract void initViews();
protected abstract void initData();
protected abstract void initListeners();
/**可以处理共同点击事件的按钮(比如像一些项目的TitleBar都有一个返回按钮)*/
protected abstract void processClick(View view);
@Override
public void onClick(View view) {
processClick(view);
}
}
说明:这里基类继承的是FragmentActivity而不是Activity,主要是考虑到主页面的viewpager嵌套了两个fragment,它的的适配器是继承FragmentPagerAdapter,这是v4包下的,所以主页面需要通过继承FragmentActivity来getSupportFragmentManager得到这个fragmentManager。
这里顺道把BaseFragment的编写也贴上,后面要用到。跟BaseActivity差不多。
public abstract class BaseFragment extends Fragment implements View.OnClickListener {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = initView(inflater, container, savedInstanceState);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
initListener();
}
protected abstract View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
protected abstract void initData();
protected abstract void initListener();
protected abstract void processClick(View view);
@Override
public void onClick(View v) {
processClick(v);
}
protected void enterActivity(Class<?> targetClass) {
startActivity(new Intent(getActivity(), targetClass));
}
protected void enterActivity(Class<?> targetClass, Bundle bundle) {
Intent intent = new Intent(getActivity(), targetClass);
intent.putExtras(bundle);
startActivity(intent);
}
说明:这里多了enterActivity()的两个重载的方法,是根据该项目需求抽取的。因为该项目中,fragment中加入的是一个listview控件,点击其中的一个item会跳转到一个activity中去,有时带数据,有时不带,为了代码整洁,所以都抽取到BaseFragment中了。
<item name="android:windowNoTitle">true</item>
1. 主页面布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/base_bg" android:orientation="vertical">
<RelativeLayout android:layout_width="match_parent" android:layout_height="55dp" android:background="@mipmap/base_titlebar_bg">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/tv_tab_video" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="视频" android:textColor="@color/indicate_line" android:textSize="18sp" />
<TextView android:id="@+id/tv_tab_audio" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="音乐" android:textColor="@color/gray_white" android:textSize="18sp" />
</LinearLayout>
<View android:id="@+id/indicate_line" android:layout_width="0dp" android:layout_height="3dp" android:layout_alignParentBottom="true" android:background="@color/indicate_line" />
</RelativeLayout>
<android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
2. 标题栏高亮及缩放:
/** * 高亮显示并且缩放标签标题 * @param position viewpager的currentItem的position */
private void highligthAndScaleTabTitle(int position) {
tvVideo.setTextColor(position == 0 ? getResources().getColor(R.color.indicate_line)
: getResources().getColor(R.color.gray_white));
tvAudio.setTextColor(position == 1 ? getResources().getColor(R.color.indicate_line)
: getResources().getColor(R.color.gray_white));
tvVideo.animate().
scaleX(position == 0 ? 1.2f : 1.0f).
scaleY(position == 0 ? 1.2f : 1.0f).
setDuration(200);
tvAudio.animate().
scaleX(position == 0 ? 1.0f : 1.2f).
scaleY(position == 0 ? 1.0f : 1.2f).
setDuration(200);
}
思考:
onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
方法中,参数position是当前fragment的位置,参数positionOffset就是手指滑动距离占屏幕总宽的比率,参数positionOffsetPixels就是滑动的像素值。贴张图再次加深对上面文字的理解。
计算指示线宽度的代码:
/** * 计算指示器的宽度 */
private void calculateIndicateLineWidth() {
Point point = new Point();
this.getWindowManager().getDefaultDisplay().getSize(point);
int screenWidth = point.x;
lineWidth = screenWidth / fragments.size();
LogUtils.i("lineWidth = " + lineWidth);
indicateLine.getLayoutParams().width = lineWidth;
indicateLine.requestLayout();
}
指示线随手指滑动的代码:(在监听viewpager的onPageScrolled()的方法里设置)
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// LogUtils.i("position = " + position + ",positionOffset = " + positionOffset
// + ",positionOffsetPixels = " + positionOffsetPixels);
float delatX = lineWidth * (position + positionOffset);
LogUtils.i("delatX = " + delatX);
indicateLine.animate().translationX(delatX).setDuration(0);
}
说明:该项目用了xUtils框架中的注解功能,省去大量的 findViewById()操作。
public class MainActivity extends BaseActivity {
@ViewInject(R.id.vp)
private ViewPager vp;
@ViewInject(R.id.tv_tab_video)
private TextView tvVideo;
@ViewInject(R.id.tv_tab_audio)
private TextView tvAudio;
@ViewInject(R.id.indicate_line)
private View indicateLine;
private List<BaseFragment> fragments;
private int lineWidth;//指示线的宽度
protected void initViews() {
setContentView(R.layout.activity_main);
ViewUtils.inject(this);
}
protected void initData() {
fragments = new ArrayList<>();
fragments.add(new VideoListFragment());
fragments.add(new AudioListFragment());
calculateIndicateLineWidth();
MainUiAdapter adapter = new MainUiAdapter(getSupportFragmentManager(), fragments);
vp.setAdapter(adapter);
highligthAndScaleTabTitle(0);
}
protected void initListeners() {
tvVideo.setOnClickListener(this);
tvAudio.setOnClickListener(this);
vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// LogUtils.i("position = " + position + ",positionOffset = " + positionOffset
// + ",positionOffsetPixels = " + positionOffsetPixels);
float delatX = lineWidth * (position + positionOffset);
LogUtils.i("delatX = " + delatX);
indicateLine.animate().translationX(delatX).setDuration(0);
}
@Override
public void onPageSelected(int position) {
highligthAndScaleTabTitle(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@Override
protected void processClick(View view) {
switch (view.getId()) {
case R.id.tv_tab_video:
vp.setCurrentItem(0);
break;
case R.id.tv_tab_audio:
vp.setCurrentItem(1);
break;
}
}
/** * 高亮显示并且缩放标签标题 * @param position viewpager的currentItem的position */
private void highligthAndScaleTabTitle(int position) {
tvVideo.setTextColor(position == 0 ? getResources().getColor(R.color.indicate_line)
: getResources().getColor(R.color.gray_white));
tvAudio.setTextColor(position == 1 ? getResources().getColor(R.color.indicate_line)
: getResources().getColor(R.color.gray_white));
tvVideo.animate().
scaleX(position == 0 ? 1.2f : 1.0f).
scaleY(position == 0 ? 1.2f : 1.0f).
setDuration(200);
tvAudio.animate().
scaleX(position == 0 ? 1.0f : 1.2f).
scaleY(position == 0 ? 1.0f : 1.2f).
setDuration(200);
}
/** * 计算指示器的宽度 */
private void calculateIndicateLineWidth() {
Point point = new Point();
this.getWindowManager().getDefaultDisplay().getSize(point);
int screenWidth = point.x;
lineWidth = screenWidth / fragments.size();
LogUtils.i("lineWidth = " + lineWidth);
indicateLine.getLayoutParams().width = lineWidth;
indicateLine.requestLayout();
}
private long exitTime = 0;
@Override
public void onBackPressed() {
if(System.currentTimeMillis() - exitTime > 2000){
ToastUtil.showShort(this, "再按一次退出手机影音");
exitTime =System.currentTimeMillis();
}else{
finish();
}
}
}
好了,先整理到这里。