关于实现界面切换功能的几个坑

在安卓应用开发中,我们经常会遇到要开发像微信和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所在程序对的布局文件相同布局。

————————————————————————————————————————————————

扫描二维码关注公众号,回复: 4550427 查看本文章

以上只是实现了点击切换的功能,就像qq一样,若要实现左右滑动切换额功能,只需使用ViewPage即可,具体的课自行百度,不是本章重点在此不加以讨论。

本博客归本人所有,转载请注明出处

猜你喜欢

转载自blog.csdn.net/weixin_42182191/article/details/81274915