在安卓应用开发中,我们经常会遇到要开发像微信和qq这种底部菜单点击切换界面或左右滑动切换界面对的功能。在开发这些功能是常见的方法(很管用)就是为四个界面(比如)添加一个共同的父类,通过继承父类的方法来动态添加四个界面,期间有些很重要又必需注意的问题在此分享一下,废话不多说直接上代码:
父类:
package pager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.TextView;
import com.hero.sockword.ContentActivity;
import com.hero.sockword.MainActivity;
import com.hero.sockword.ServiceLock;
/**
* Created by HERO on 2018/5/12.
*/
public abstract class BasePager{
public boolean isInitData;
public final Context context;
public View rootView;
/**
* 上下文
*/
public BasePager(Context context) {
this.context = context;
rootView = initView();
}
/**
* 抽象方法,强制孩子实现
*/
public abstract View initView();
/**
* 初始化数据
*/
public void initData() {
}
}
根据需要,这里父类强制子类实现几个方法如上,
子类
package pager;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.hero.sockword.R;
import mySql.GreenDaoToos;
import mySql.SqlTool;
/**
* Created by HERO on 2018/5/12.
*/
public class GoOverPager extends BasePager implements View.OnClickListener{
@Override
public void onClick(View v) {
//这里添加点击事件
}
/**
* 上下文
*
* @param context
*/
public GoOverPager(Context context) {
super(context);
initData();
}
@Override
public View initView() {
View view=View.inflate(context, R.layout.goover_pager,null);//解析子类对的布局文件,根据需要自己设置
initData();
return view;
}
@Override
public void initData() {
super.initData();
Log.i("Gover","数据被初始化啦!");
/**
* 初始化数据以及相关操作
*/
}
}
为了简便,这里只列出一个子类的代码,我这里总共添加了四个子类,分别是,GoOverPager,HomePager,SetPager和VocabularyPager,然后就是如何在主程序中实现切换的功能:
主程序
package com.hero.sockword;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;
import android.widget.Toast;
import java.util.ArrayList;
import mySql.SqlTool;
import pager.BasePager;
import pager.GoOverPager;
import pager.HomePager;
import pager.SetPager;
import pager.VocabularyPager;
import vocabulary.Vocabulary;
/**
* Created by HERO on 2018/5/11.
*/
public class ContentActivity extends FragmentActivity {
private ArrayList<BasePager> basePagers;
private RadioGroup radioGroup;
private int position;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
//添加四个界面,即四个子类
basePagers=new ArrayList<BasePager>();
basePagers.add(new HomePager(this));
basePagers.add(new GoOverPager(this));
basePagers.add(new VocabularyPager(this));
basePagers.add(new SetPager(this));
radioGroup= (RadioGroup) findViewById(R.id.rg_bottom_tag);//底部按钮
radioGroup.setOnCheckedChangeListener(new MyOnCheckedListener());
radioGroup.check(R.id.rb_home);
}
//底部按钮点击事件,记录当前位置以便设置当前界面
private class MyOnCheckedListener implements RadioGroup. OnCheckedChangeListener {
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
switch (checkedId){
case R.id.rb_home:
position=0;
break;
case R.id.rb_over:
Log.i("ContentActivity","GoverPager被选中啦!");
position=1;
break;
case R.id.rb_words:
position=2;
break;
case R.id.rb_set:
position=3;
break;
}
setFragment();
}
}
private void setFragment() {
//获取Fragment
FragmentManager fg=getSupportFragmentManager();
//开启事务
FragmentTransaction ft=fg.beginTransaction();
// MyFragment mf=new MyFragment();
MyFragment.basePager=getBasePager();
//动态替换四个界面
ft.replace(R.id.fg_content,new MyFragment());
ft.commit();
}
private BasePager getBasePager() {
//这一步很重要,用到了刚才所说的position,即当前应该替换显示的界面,从basePagers中获取,这也正是为什么要使用继承父类的方法来实现
BasePager basePager=basePagers.get(position);
return basePager;
}
public static class MyFragment extends Fragment {
private static BasePager basePager;
public MyFragment(){
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("TEST","MyFragment Inside");
return basePager.rootView;
}
}
}
主程序的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:background="#FFFFFF"
android:layout_height="match_parent">
<!--替换的界面区域-->
<FrameLayout
android:id="@+id/fg_content"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/titlebar"/>
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<!--底部四个按钮,主要是用于实现点击切换的功能-->
<RadioGroup
android:id="@+id/rg_bottom_tag"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="3dp">
<RadioButton
android:id="@+id/rb_home"
style="@style/bottom_tag_style"
android:drawableTop="@drawable/rb_home_drawable_selector"
android:text="首页" />
<RadioButton
android:id="@+id/rb_over"
style="@style/bottom_tag_style"
android:drawableTop="@drawable/rb_over_selector"
android:text="复习" />
<RadioButton
android:id="@+id/rb_words"
style="@style/bottom_tag_style"
android:drawableTop="@drawable/rb_words_selector"
android:text="词库" />
<RadioButton
android:id="@+id/rb_set"
style="@style/bottom_tag_style"
android:drawableTop="@drawable/rb_set_selector"
android:text="设置" />
</RadioGroup>
</LinearLayout>
</LinearLayout>
上面的代码都不难看懂(本人在校期间完成的一个小项目,比较简单),相信大家都会,接下来说下写这篇文章的重点的几个坑。
1.第一个坑
在子类中直接调用startActivity、打印log报空指针错误(但凡直接调用子类的对象都会报错,如GoOverPager.this)
解释:这是因为子类继承于父类,而这里
ArrayList<BasePager> basePagers=new ArrayList<BasePager>();
使用的是其父类的对象,然后具体到其子类,然后再根据需要进行替代当前界面,这里只是显示子类,子类的对象引用在此过程中不能直接使用,必须使用其父类对象(大概就是这个意思,具体的可以参考java继承相关的知识,此处不做详解),所以这里我在父类中添加了一个父类的对象
/**
* 上下文
*/
public BasePager(Context context) {
this.context = context;//父类的对象具体为子类的对象,保存起来才能用
rootView = initView();
}
然后在需要时再使用context.startActivity(......);等涉及到对象引用的操作
2.布局文件未能全部显示或絮乱
在这里,动态替换FragmentLayout里面的布局文件时,必须要注意布局文件使用的是相同的Layout布局(如同是FramLayout)
,四个子类解析的布局文件要使用相同的帧格式,最好是和主程序FragmentLaout所在程序对的布局文件相同布局。
————————————————————————————————————————————————
以上只是实现了点击切换的功能,就像qq一样,若要实现左右滑动切换额功能,只需使用ViewPage即可,具体的课自行百度,不是本章重点在此不加以讨论。
本博客归本人所有,转载请注明出处