1.实现原理

通过继承LinearLayout实现水平布局,再动态新建一个垂直布局的linearLayout,根据传入的标题名称的长度动态创建TextView和ImageView,根据顺序加到linearlayout中。

Android自定义底部导航栏,链式封装多种样式

Android自定义底部导航栏,链式封装多种样式

Android自定义底部导航栏,链式封装多种样式

2.主类BottomView继承LinearLayout

public class BottomView extends LinearLayout {
    private TextView textView;
    private List<String> name;
    private List<Object> image;
    private List<Object> images;
    private Context context;
    private LinearLayout linearLayout;
    private ImageView imageView;
    private int color;
    private int size = 10;
    private int checkColor;
    private int width = 80;
    private int height = 80;
    private List<LinearLayout> linearLayouts;
    private List<ImageView> imageViews;
    private List<TextView> textViews;
    private boolean open = true;
    private boolean square = true;
    private Object imageContet;
    private int imageWidth = 200;
    private int imageHeight = 200;
    private OnClick onClick;
    private int imageBottom=20;

    public void setOnClick(BottomView.OnClick onClick) {
        this.onClick = onClick;
    }

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

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

    public BottomView init() {
        //设置垂直linearlayout的布局
        LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        layoutParams.weight = 1;
        layoutParams.gravity = Gravity.CENTER;
        LayoutParams imageLayoutParams = new LayoutParams(width, height);
        imageLayoutParams.gravity = Gravity.CENTER;

        imageViews = new ArrayList<>();
        linearLayouts = new ArrayList<>();
        textViews = new ArrayList<>();
        this.setClipChildren(false);
        //判断是否要打开中间按钮
        if (open) {
            for (int i = 0; i < name.size(); i++) {
                final int finalI = i;
                //判断view的个数,是奇数即使打开了中间按钮也不起作用
                if ((name.size() % 2) != 0) {
                    textView = new TextView(context);
                    textView.setText(name.get(i));
                    textView.setGravity(Gravity.CENTER_HORIZONTAL);
                    textView.setTextColor(color);
                    textView.setTextSize(size);
                    textViews.add(textView);

                    imageView = new ImageView(context);
                    Glide.with(context).load(image.get(i)).into(imageView);
                    imageView.setLayoutParams(imageLayoutParams);
                    imageViews.add(imageView);

                    linearLayout = new LinearLayout(context);
                    linearLayout.setOrientation(VERTICAL);
                    linearLayout.setLayoutParams(layoutParams);
                    linearLayout.addView(imageView);
                    linearLayout.addView(textView);
                    linearLayouts.add(linearLayout);
                } else {
                    textView = new TextView(context);
                    textView.setText(name.get(i));
                    textView.setGravity(Gravity.CENTER_HORIZONTAL);
                    textView.setTextColor(color);
                    textView.setTextSize(size);
                    textViews.add(textView);

                    imageView = new ImageView(context);
                    Glide.with(context).load(image.get(i)).into(imageView);
                    imageView.setLayoutParams(imageLayoutParams);
                    imageViews.add(imageView);

                    linearLayout = new LinearLayout(context);
                    linearLayout.setOrientation(VERTICAL);
                    linearLayout.setLayoutParams(layoutParams);
                    //判断是否刚好创建了一半的布局,是的话创建中间大按钮
                    if (i == name.size() / 2) {
                        this.setClipChildren(true);
                        LayoutParams layoutParamss = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                        layoutParamss.gravity = Gravity.CENTER;
                        layoutParamss.weight=1;
                        LinearLayout linearLayout = new LinearLayout(context);
                        linearLayout.setLayoutParams(layoutParamss);
                        linearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
                        LayoutParams imageLayoutParamss = new LayoutParams(imageWidth, imageHeight);
                        imageLayoutParamss.gravity = Gravity.CENTER;
                        if (!square) {
                            this.setClipChildren(false);
                            imageLayoutParamss.setMargins(0, 0, 0, imageBottom);
                        }
                        ImageView imageViews = new ImageView(context);
                        Glide.with(context).load(imageContet).into(imageViews);
                        imageViews.setLayoutParams(imageLayoutParamss);
                        linearLayout.addView(imageViews);
                        linearLayouts.add(linearLayout);
                        linearLayout.setOnClickListener(new OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                setChecked();
                                onClick.onClick(finalI);
                            }
                        });
                        this.addView(linearLayout);
                    }
                    linearLayout.addView(imageView);
                    linearLayout.addView(textView);
                    linearLayouts.add(linearLayout);
                }

                linearLayout.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setChecked();
                        textViews.get(finalI).setTextColor(checkColor);
                        Glide.with(context).load(images.get(finalI)).into(imageViews.get(finalI));
                        if ((name.size() % 2) != 0) {
                            onClick.onClick(finalI);
                        } else {
                            if (finalI >= name.size() / 2) {
                                onClick.onClick(finalI + 1);
                            } else {
                                onClick.onClick(finalI);
                            }
                        }
                    }
                });

                this.addView(linearLayout);
            }

        } else {
            for (int i = 0; i < name.size(); i++) {
                textView = new TextView(context);
                textView.setText(name.get(i));
                textView.setGravity(Gravity.CENTER_HORIZONTAL);
                textView.setTextColor(color);
                textView.setTextSize(size);
                textViews.add(textView);

                imageView = new ImageView(context);
                Glide.with(context).load(image.get(i)).into(imageView);
                imageView.setLayoutParams(imageLayoutParams);
                imageViews.add(imageView);

                linearLayout = new LinearLayout(context);
                linearLayout.setOrientation(VERTICAL);
                linearLayout.setLayoutParams(layoutParams);
                linearLayout.addView(imageView);
                linearLayout.addView(textView);
                linearLayouts.add(linearLayout);

                final int finalI = i;
                linearLayout.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setChecked();
                        textViews.get(finalI).setTextColor(checkColor);
                        Glide.with(context).load(images.get(finalI)).into(imageViews.get(finalI));
                        onClick.onClick(finalI);
                    }
                });

                this.addView(linearLayout);
            }
        }
        return this;
    }

    /**
     * 设置item的文字和图片
     * @param name
     * @param image
     * @return
     */
    public BottomView setNameOrImage(List<String> name, List<Object> image) {
        this.name = name;
        this.image = image;
        return this;
    }

    /**
     * 设置文字颜色
     * @param color
     * @return
     */
    public BottomView setTextColors(int color) {
        this.color = color;
        return this;
    }

    /**
     * 设置文字的大小
     * @param size
     * @return
     */
    public BottomView setTextSize(int size) {
        this.size = size;
        return this;
    }

    /**
     * 设置选中的item的文字颜色
     * @param checkColor
     * @return
     */
    public BottomView setTextCheckColor(int checkColor) {
        this.checkColor = checkColor;
        return this;
    }

    /**
     * 设置item选中的图片
     * @param images
     * @return
     */
    public BottomView setImageCheck(List<Object> images) {
        this.images = images;
        return this;
    }

    /**
     * 设置中间图片的下边距
     * @param bottom
     * @return
     */
    public BottomView setImageBottom(int bottom) {
        this.imageBottom = bottom;
        return this;
    }

    /**
     * 设置item图片的高度和宽度
     * @param width
     * @param height
     * @return
     */
    public BottomView setImageWidthHeight(int width, int height) {
        this.width = width;
        this.height = height;
        return this;
    }

    /**
     * 设置中间大按钮的宽度和高度
     * @param width
     * @param height
     * @return
     */
    public BottomView setImagesWidthHeight(int width, int height) {
        this.imageWidth = width;
        this.imageHeight = height;
        return this;
    }

    /**
     * 设置图片全部未选中
     */
    public void setChecked() {
        for (int i = 0; i < textViews.size(); i++) {
            textViews.get(i).setTextColor(color);
            Glide.with(context).load(image.get(i)).into(imageViews.get(i));
        }
    }

    /**
     * 设置是否显示中间大按钮
     * @param open
     * @return
     */
    public BottomView setOpen(boolean open) {
        this.open = open;
        return this;
    }

    /**
     * 设置是否让大按钮居中
     * @param square
     * @return
     */
    public BottomView setSquare(boolean square) {
        this.square = square;
        return this;
    }

    /**
     * 设置中间大按钮的图片
     * @param image
     * @return
     */
    public BottomView setMiddleImage(Object image) {
        this.imageContet = image;
        return this;
    }

    /**
     * 设置选中的item
     * @param position
     */
    public void setPosition(int position) {
        setChecked();
        textViews.get(position).setTextColor(checkColor);
        Glide.with(context).load(images.get(position)).into(imageViews.get(position));
    }

    public interface OnClick {
        void onClick(int position);
    }
}

3.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:background="#ccc"
    android:clipChildren="false">
 <com.dianna.bottomview.BottomView
        android:id="@+id/bottoms"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:background="#fff"
        android:clipChildren="false"
        android:orientation="horizontal"></com.dianna.bottomview.BottomView>
</RelativeLayout>

注意:要让中间大按钮突出父布局的布局范围要在父布局加上android:clipChildren="false"这行关键代码

4.activity

public class MainActivity extends AppCompatActivity implements BottomView.OnClick {
    private BottomView bottomView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        bottomView = findViewById(R.id.bottoms);

        bottomView.setTextColors(Color.BLACK)//设置未选中标题颜色
                .setOpen(true)//是否显示中间大按钮,当标题个数为奇数是,自动不显示按钮
                .setTextCheckColor(Color.BLUE)//设置选中标题颜色
                .setSquare(true)//设置按钮是否居中还是往上突起,当setOpen(false)此设置无效
                .setImageCheck(imagesList)//设置选中时图片
                .setMiddleImage(R.mipmap.difennaa)//设置中间大按钮的图片
                .setImagesWidthHeight(150, 150)//设置中间大按钮的高宽度
                .setImageBottom(40)//设置大按钮的下边距
                .setNameOrImage(nameList, imageList)//设置每个item的标题和图片
                .setImageWidthHeight(70, 70)//设置item图片的高宽度
                .init();//初始化
        bottomView.setOnClick(this);//点击回调
        bottomView.setPosition(0);//设置选中的item
        frameLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

    private void initData() {
        nameList = new ArrayList<>();
        imageList = new ArrayList<>();
        imagesList = new ArrayList<>();
        nameList.add("首页");
        nameList.add("分类");
        nameList.add("发现");
        nameList.add("我的");
        nameList.add("我的");
        imageList.add(R.mipmap.shouye);
        imageList.add(R.mipmap.fenlei);
        imageList.add(R.mipmap.gouwuche);
        imageList.add(R.mipmap.geren);
        imageList.add(R.mipmap.geren);
        imagesList.add(R.mipmap.shouye_check);
        imagesList.add(R.mipmap.fenlei_check);
        imagesList.add(R.mipmap.gouwuche_check);
        imagesList.add(R.mipmap.geren_check);
        imagesList.add(R.mipmap.geren_check);
    }

    @Override
    public void onClick(int position) {
        Toast.makeText(this, "这是第" + (position + 1) + "个", Toast.LENGTH_SHORT).show();
    }
}

通过简单对LinearLayout继承与封装,实现了底部导航栏的多种样式实现,以后遇到项目中有底部导航栏再也不用重新编写繁琐与复杂的代码了。

相关文章:

  • 2022-12-23
  • 2021-08-29
  • 2022-12-23
  • 2021-11-24
  • 2021-09-21
  • 2021-09-12
  • 2021-04-08
  • 2022-12-23
猜你喜欢
  • 2021-09-01
  • 2021-07-05
  • 2022-12-23
  • 2022-12-23
  • 2021-07-10
  • 2022-12-23
  • 2021-10-11
相关资源
相似解决方案