封装一个动态导航栏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DongGeDeBoKe/article/details/83241249

《android中如何打造一个动态的底部导航栏》
在上一篇只是教大家一些基础的东西,今天来完成一个真正的动态底部导航栏的项目,本项目还是会分几步来完成,不懂的可以根据步骤一步一步的来,每个步骤都会解释清楚,相信大家一定会学习到一些东西,相信学习之后,自己也能有自己的一些自定义控件,那就开始吧!
第一步:新建一个类名字为NavFootView,然后继承LinearLayout,要重写至少两个构造方法.

public class NavFootView extends LinearLayout {

    public NavFootView(Context context) {
        super(context);
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

第二步:就是如何动态获取该控件的宽高,和手指点击该控件后的坐标,为什么要这样做呢?因为我们只有获取到控件的宽高,才能进行计算出每个图标占多少的空间。

public class NavFootView extends LinearLayout {
    public NavFootView(Context context) {
        super(context);
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    //获取触摸的坐标
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("data-->", "" + event.getX());
        Log.i("data-->", "" + event.getX());

        return super.onTouchEvent(event);
    }
    //获取控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取控件的宽
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取控件的高
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        Log.i("data-->", "宽:" + parentWidth);
        Log.i("data-->", "高:" + parentHeight);
        this.setMeasuredDimension(parentWidth, parentHeight);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

这个时候就可以获取到控件的宽高和触摸的坐标。
第三步:向导航栏内动态添加数据
在做这个之前我们要先进行物理数据的储备,因为之后的操作需要根据这些数据,进行操作,比如导航栏点击之后图标变成什么样子,字体的颜色等。新建几个方法采用java中的链式编程的方式.

//添加item
    public NavFootView addItem(String title, int icBefore, int icAfter) {
        return this;
    }
 //进行项目的创建--所有的操作放在这个地方
    public void build(){
       
    }
    //这个方法是上篇的一个方法就是用于动态生成
 private TextView getTextView(String title, int drawableId) {
        TextView textView = new TextView(context);
        textView.setText(title);
        //这一步就是让字体居中
        textView.setGravity(Gravity.CENTER);
        //给TextView设置布局参数--第一个参数是宽,第二个参数是高,第三个参数是相当于 android:layout_weight="1"
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1.0f);
        textView.setLayoutParams(params);
        textView.setTextColor(Color.BLACK);
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
        return textView;
    }

下边就是第三步整体的代码:

public class NavFootView extends LinearLayout {
    public NavFootView(Context context) {
        super(context);
        this.context = context;
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
    }
    //点击之前的图标
    private Map<String, Integer> icBeforeMap = new HashMap<>();
    //点击之后的图标
    private Map<String, Integer> icAfterMap = new HashMap<>();
    //存储标题
    private List<String> titleList = new ArrayList<>();
    //获取控件的宽
    private int parentWidth;
    //获取控件的高
    private int parentHeight;
    private Context context;
    //获取触摸的坐标
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        return super.onTouchEvent(event);
    }
    //获取控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取控件的宽
        parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取控件的高
        parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth, parentHeight);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    //添加item
    public NavFootView addItem(String title, int icBefore, int icAfter) {
        titleList.add(title);
        icBeforeMap.put(title, icBefore);
        icAfterMap.put(title, icAfter);
        return this;
    }
    //进行项目的创建--所有的操作放在这个地方
    public void build() {
        Iterator<String> iterator = titleList.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            this.addView(getTextView(next,icBeforeMap.get(next)));
        }
    }
    //创建一个TextView
    private TextView getTextView(String title, int drawableId) {
        TextView textView = new TextView(context);
        textView.setText(title);
        //这一步就是让字体居中
        textView.setGravity(Gravity.CENTER);
        //给TextView设置布局参数--第一个参数是宽,第二个参数是高,第三个参数是相当于 android:layout_weight="1"
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1.0f);
        textView.setLayoutParams(params);
        textView.setTextColor(Color.BLACK);
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
        return textView;
    }
}

那怎么使用呢?请看下边
首先就是在xml里进行配置,本教程采用的是在xml里配置的方式,也可以用代码动态也可以,只是为了方便而已.
xml中配置

<?xml version="1.0" encoding="utf-8"?>
<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"
  tools:context="com.listview.MainActivity">
  <com.listview.NavFootView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/container"
    android:orientation="horizontal">
  </com.listview.NavFootView>
</LinearLayout>

在代码中使用

public class MainActivity extends AppCompatActivity {
    NavFootView container;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        container = findViewById(R.id.container);
        container.addItem("首页", R.mipmap.ads1, R.mipmap.ads2);
        container.addItem("消息", R.mipmap.datav1, R.mipmap.datav2);
        container.addItem("联系人", R.mipmap.openad1, R.mipmap.openad2);
        container.addItem("我的", R.mipmap.re1, R.mipmap.re2);
        container.build();
    }
}

效果图:
在这里插入图片描述
现在短短的几行,就已经显示出来了,但是这样是不够的,怎么实现点击之后图标颜色变换呢?
第四步:如何改变点击之后图标的变换和字体颜色的变换?
这个时候就要用到第一步的那两个方法了,一个是获得触摸的坐标,一个是获得控件宽高,那怎么使用呢?这个时候新建一个方法

 //获取点击的是哪个
    public void selectPage(int index){

    }

如何使用呢?直接这样使用就好了, int index = (int)(x/(parentWidth/titleList.size()));这个计算的理念是,导航栏平分之后,就只需要计算出触摸的区域是在哪个区域就可以了

 //获取触摸的坐标
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
       int index  = (int) (x/(parentWidth/titleList.size()));
        selectPage(index);
        return super.onTouchEvent(event);
    }

既然数据要添加完了,这个时候就是要获取点击的那个控件了.新建一个方法

    //给TextView设置图片
    private void setTextViewDrawable(TextView textView, int drawableId) {
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
    }

这个时候selectPage这个方法就变成

 //获取点击的是哪个
    public void selectPage(int index) {
        //获得控件总共的数量
        int childCount = this.getChildCount();
        for (int i = 0; i < childCount; i++) {
            TextView textView = (TextView) this.getChildAt(i);
            if (index == i) {
                //选中
                textView.setTextColor(Color.RED);
                setTextViewDrawable(textView,icAfterMap.get(textView.getText().toString().trim()));
            } else {
                //未选中
                textView.setTextColor(Color.BLACK);
                setTextViewDrawable(textView,icBeforeMap.get(textView.getText().toString().trim()));
            }
        }
    }

整体代码:

public class NavFootView extends LinearLayout {
    public NavFootView(Context context) {
        super(context);
        this.context = context;
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
    }
    //点击之前的图标
    private Map<String, Integer> icBeforeMap = new HashMap<>();
    //点击之后的图标
    private Map<String, Integer> icAfterMap = new HashMap<>();
    //存储标题
    private List<String> titleList = new ArrayList<>();
    //获取控件的宽
    private int parentWidth;
    //获取控件的高
    private int parentHeight;
    private Context context;
    //获取触摸的坐标
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        int index = (int) (x / (parentWidth / titleList.size()));
        selectPage(index);
        return super.onTouchEvent(event);
    }
    //获取控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取控件的宽
        parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取控件的高
        parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth, parentHeight);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    //添加item
    public NavFootView addItem(String title, int icBefore, int icAfter) {
        titleList.add(title);
        icBeforeMap.put(title, icBefore);
        icAfterMap.put(title, icAfter);
        return this;
    }
    //进行项目的创建--所有的操作放在这个地方
    public void build() {
        Iterator<String> iterator = titleList.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            this.addView(getTextView(next, icBeforeMap.get(next)));
        }
    }
    //获取点击的是哪个
    public void selectPage(int index) {
        //获得控件总共的数量
        int childCount = this.getChildCount();
        for (int i = 0; i < childCount; i++) {
            TextView textView = (TextView) this.getChildAt(i);
            if (index == i) {
                //选中
                textView.setTextColor(Color.RED);
                setTextViewDrawable(textView,icAfterMap.get(textView.getText().toString().trim()));
            } else {
                //未选中
                textView.setTextColor(Color.BLACK);
                setTextViewDrawable(textView,icBeforeMap.get(textView.getText().toString().trim()));
            }
        }
    }
    //创建一个TextView
    private TextView getTextView(String title, int drawableId) {
        TextView textView = new TextView(context);
        textView.setText(title);
        //这一步就是让字体居中
        textView.setGravity(Gravity.CENTER);
        //给TextView设置布局参数--第一个参数是宽,第二个参数是高,第三个参数是相当于 android:layout_weight="1"
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT,
            1.0f);
        textView.setLayoutParams(params);
        textView.setTextColor(Color.BLACK);
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
        return textView;
    }
    //给TextView设置图片
    private void setTextViewDrawable(TextView textView, int drawableId) {
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
    }
}

效果如下:
在这里插入图片描述
是不是越来越完善了呢,对的现在已经完成了一大步了。
第五步:也是最重要的一步了,导航栏的作用是什么,大家都知道是用于用户单击跳转到其他页面的,导航栏一般在Fragment和Activity中都会使用,那首先就是如何才能在Fragment使用呢?
首先就是修改activity的xml文件,加入帧布局

<?xml version="1.0" encoding="utf-8"?>
<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"
  tools:context="com.listview.MainActivity"
  android:orientation="vertical">
  <FrameLayout
    android:id="@+id/frameLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
  </FrameLayout>
  <com.listview.NavFootView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/container"
    android:orientation="horizontal">
  </com.listview.NavFootView>
</LinearLayout>

然后就是修改之前的一个方法,就是添加数据的那个方法,加入能够添加Fragment的功能,就是多了一个物理资源的储备.

   //添加item
    public NavFootView addItem(String title, int icBefore, int icAfter, Fragment fragment) {
        titleList.add(title);
        icBeforeMap.put(title, icBefore);
        icAfterMap.put(title, icAfter);
        fragmentMap.put(title, fragment);
        return this;
    }

再新建处理跳转的方法和设置Fragment布局id的方法

    //跳转页面
    private void switchFragment(String title) {

    }
     public void setFrameLayoutId(int frameLayoutId){
        this.frameLayoutId = frameLayoutId;
    }

处理跳转的方法:

  private Fragment currentFragment = null;
    //跳转页面
    private void switchFragment(String title) {
        Fragment fragment = fragmentMap.get(title);
        //开启事务
        FragmentTransaction fragmentTransaction = ((Activity) context).getFragmentManager()
            .beginTransaction();
        if (fragment.isAdded()) {
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment).show(fragment);
            } else {
                fragmentTransaction.show(fragment);
            }
        } else {
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment).add(frameLayoutId, fragment);
            } else {
                fragmentTransaction.add(frameLayoutId, fragment);
            }
        }
        currentFragment = fragment;
        fragmentTransaction.commit();
    }

好了到这里,如果仅仅是使用,现在已经可以使用了,现在先贴出全部的代码:
首先贴出导航栏的代码

public class NavFootView extends LinearLayout {
    public NavFootView(Context context) {
        super(context);
        this.context = context;
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }
    public NavFootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
    }
    //点击之前的图标
    private Map<String, Integer> icBeforeMap = new HashMap<>();
    //点击之后的图标
    private Map<String, Integer> icAfterMap = new HashMap<>();
    //存储标题
    private List<String> titleList = new ArrayList<>();
    //获取控件的宽
    private int parentWidth;
    //获取控件的高
    private int parentHeight;
    //存储Fragment
    private Map<String, Fragment> fragmentMap = new HashMap<>();
    private Context context;
    //布局id
    private int frameLayoutId;
    //获取触摸的坐标
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        int index = (int) (x / (parentWidth / titleList.size()));
        selectPage(index);
        return super.onTouchEvent(event);
    }
    //获取控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取控件的宽
        parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取控件的高
        parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth, parentHeight);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    //添加item
    public NavFootView addItem(String title, int icBefore, int icAfter, Fragment fragment) {
        titleList.add(title);
        icBeforeMap.put(title, icBefore);
        icAfterMap.put(title, icAfter);
        fragmentMap.put(title, fragment);
        return this;
    }
    //进行项目的创建--所有的操作放在这个地方
    public void build() {
        Iterator<String> iterator = titleList.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            this.addView(getTextView(next, icBeforeMap.get(next)));
        }
    }
    //获取点击的是哪个
    public void selectPage(int index) {
        //获得控件总共的数量
        int childCount = this.getChildCount();
        for (int i = 0; i < childCount; i++) {
            TextView textView = (TextView) this.getChildAt(i);
            String title = textView.getText().toString().trim();
            if (index == i) {
                //选中
                textView.setTextColor(Color.RED);
                setTextViewDrawable(textView, icAfterMap.get(title));
                switchFragment(title);
            } else {
                //未选中
                textView.setTextColor(Color.BLACK);
                setTextViewDrawable(textView, icBeforeMap.get(title));
            }
        }
    }
    //设置布局id
    public void setFrameLayoutId(int frameLayoutId) {
        this.frameLayoutId = frameLayoutId;
    }
    private Fragment currentFragment = null;
    //跳转页面
    private void switchFragment(String title) {
        Fragment fragment = fragmentMap.get(title);
        //开启事务
        FragmentTransaction fragmentTransaction = ((Activity) context).getFragmentManager()
            .beginTransaction();
        if (fragment.isAdded()) {
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment).show(fragment);
            } else {
                fragmentTransaction.show(fragment);
            }
        } else {
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment).add(frameLayoutId, fragment);
            } else {
                fragmentTransaction.add(frameLayoutId, fragment);
            }
        }
        currentFragment = fragment;
        fragmentTransaction.commit();
    }
    //创建一个TextView
    private TextView getTextView(String title, int drawableId) {
        TextView textView = new TextView(context);
        textView.setText(title);
        //这一步就是让字体居中
        textView.setGravity(Gravity.CENTER);
        //给TextView设置布局参数--第一个参数是宽,第二个参数是高,第三个参数是相当于 android:layout_weight="1"
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT,
            1.0f);
        textView.setLayoutParams(params);
        textView.setTextColor(Color.BLACK);
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
        return textView;
    }

    //给TextView设置图片
    private void setTextViewDrawable(TextView textView, int drawableId) {
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
    }
}

再贴出使用过程的代码:

public class MainActivity extends AppCompatActivity {
    NavFootView container;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        container = findViewById(R.id.container);
        container.setFrameLayoutId(R.id.fl_container);
        container.addItem("首页", R.mipmap.ads1, R.mipmap.ads2, new HomeFragment());
        container.addItem("消息", R.mipmap.datav1, R.mipmap.datav2, new Home2Fragment());
        container.addItem("联系人", R.mipmap.openad1, R.mipmap.openad2, new Home3Fragment());
        container.addItem("我的", R.mipmap.re1, R.mipmap.re2, new Home4Fragment());
        container.build();
    }
}

效果图:
在这里插入图片描述
看到这么短短几行的代码就完成了,动态导航栏的功能,还能实现跳转是不是感觉很惊喜,对就是这么简单,相信大家在一步一步的过程也能学到一些东西。下边就是对这个导航栏的加强,如果有兴趣的话,那就跟我继续奋斗吧。
第六步:设置默认页面,相信很多小伙伴都知道,比如首页,打开就会自动跳转到首页.
新建一个方法

    //设置默认跳转页面
    public void setDefaultIndex(int defaultIndex) {
        this.defaultIndex = defaultIndex;
    }

重写build(),简单的一句就实现了默认跳转

 //进行项目的创建--所有的操作放在这个地方
    public void build() {
        Iterator<String> iterator = titleList.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            this.addView(getTextView(next, icBeforeMap.get(next)));
        }
        if (defaultIndex != -1) {
            selectPage(defaultIndex);
        }
    }

第七步:之前的fragment的跳转已经完成了,那关于Activity的跳转呢?
之后再更新,好累了,一口气完成这么多,下次再完善,代码,大家也可以自行进行修改,还有就是一些小伙伴,会在这里报错,大家注意Fragment有两个版本,所以大家按需求导入特定的包,使用也会有一些区别,就不一一介绍了,遇到问题自己百度解决吧!
//跳转页面
private void switchFragment(String title) {
Fragment fragment = fragmentMap.get(title);
//开启事务
FragmentTransaction fragmentTransaction = ((Activity) context).getFragmentManager()
.beginTransaction();
if (fragment.isAdded()) {
if (currentFragment != null) {
fragmentTransaction.hide(currentFragment).show(fragment);
} else {
fragmentTransaction.show(fragment);
}
} else {
if (currentFragment != null) {
fragmentTransaction.hide(currentFragment).add(frameLayoutId, fragment);
} else {
fragmentTransaction.add(frameLayoutId, fragment);
}
}
currentFragment = fragment;
fragmentTransaction.commit();
}`
下边粘贴处全部的代码,分享给大家

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class NavFootView extends LinearLayout {

    public NavFootView(Context context) {
        super(context);
        this.context = context;
    }

    public NavFootView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public NavFootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
    }

    //点击之前的图标
    private Map<String, Integer> icBeforeMap = new HashMap<>();
    //点击之后的图标
    private Map<String, Integer> icAfterMap = new HashMap<>();
    //存储标题
    private List<String> titleList = new ArrayList<>();
    //获取控件的宽
    private int parentWidth;
    //获取控件的高
    private int parentHeight;
    //存储Fragment
    private Map<String, Fragment> fragmentMap = new HashMap<>();
    private Context context;
    //布局id
    private int frameLayoutId;
    //默认跳转的页面
    private int defaultIndex = -1;
    //碎片处理
    private Fragment currentFragment = null;

    //获取触摸的坐标
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        int index = (int) (x / (parentWidth / titleList.size()));
        selectPage(index);
        return super.onTouchEvent(event);
    }

    //获取控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取控件的宽
        parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取控件的高
        parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth, parentHeight);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    //添加item
    public NavFootView addItem(String title, int icBefore, int icAfter, Fragment fragment) {
        titleList.add(title);
        icBeforeMap.put(title, icBefore);
        icAfterMap.put(title, icAfter);
        fragmentMap.put(title, fragment);
        return this;
    }

    //进行项目的创建--所有的操作放在这个地方
    public void build() {
        Iterator<String> iterator = titleList.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            this.addView(getTextView(next, icBeforeMap.get(next)));
        }
        if (defaultIndex != -1) {
            selectPage(defaultIndex);
        }
    }

    //获取点击的是哪个
    public void selectPage(int index) {
        //获得控件总共的数量
        int childCount = this.getChildCount();
        for (int i = 0; i < childCount; i++) {
            TextView textView = (TextView) this.getChildAt(i);
            String title = textView.getText().toString().trim();
            if (index == i) {
                //选中
                textView.setTextColor(Color.RED);
                setTextViewDrawable(textView, icAfterMap.get(title));
                switchFragment(title);
            } else {
                //未选中
                textView.setTextColor(Color.BLACK);
                setTextViewDrawable(textView, icBeforeMap.get(title));
            }
        }
    }

    //设置布局id
    public void setFrameLayoutId(int frameLayoutId) {
        this.frameLayoutId = frameLayoutId;
    }

    //设置默认跳转页面
    public void setDefaultIndex(int defaultIndex) {
        this.defaultIndex = defaultIndex;
    }

    //跳转页面
    private void switchFragment(String title) {
        Fragment fragment = fragmentMap.get(title);
        //开启事务
        FragmentTransaction fragmentTransaction = ((Activity) context).getFragmentManager()
            .beginTransaction();
        if (fragment.isAdded()) {
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment).show(fragment);
            } else {
                fragmentTransaction.show(fragment);
            }
        } else {
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment).add(frameLayoutId, fragment);
            } else {
                fragmentTransaction.add(frameLayoutId, fragment);
            }
        }
        currentFragment = fragment;
        fragmentTransaction.commit();
    }

    //创建一个TextView
    private TextView getTextView(String title, int drawableId) {
        TextView textView = new TextView(context);
        textView.setText(title);
        //这一步就是让字体居中
        textView.setGravity(Gravity.CENTER);
        //给TextView设置布局参数--第一个参数是宽,第二个参数是高,第三个参数是相当于 android:layout_weight="1"
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT,
            1.0f);
        textView.setLayoutParams(params);
        textView.setTextColor(Color.BLACK);
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
        return textView;
    }

    //给TextView设置图片
    private void setTextViewDrawable(TextView textView, int drawableId) {
        Drawable drawable = getResources().getDrawable(drawableId);
        //这句话一定要写
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // setCompoundDrawables(left ,top ,right, bottom);
        textView.setCompoundDrawables(null, drawable, null, null);
    }

}

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    NavFootView container;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        container = findViewById(R.id.container);
        container.setFrameLayoutId(R.id.fl_container);
        container.setDefaultIndex(0);
        container.addItem("首页", R.mipmap.ads1, R.mipmap.ads2, new HomeFragment());
        container.addItem("消息", R.mipmap.datav1, R.mipmap.datav2, new Home2Fragment());
        container.addItem("联系人", R.mipmap.openad1, R.mipmap.openad2, new Home3Fragment());
        container.addItem("我的", R.mipmap.re1, R.mipmap.re2, new Home4Fragment());
        container.build();
    }
}

简单方便的动态导航栏就完成了,谢谢大家支持,后续会跟大家分享更多的东西.

猜你喜欢

转载自blog.csdn.net/DongGeDeBoKe/article/details/83241249