RadioGroup底部Tab的动态添加

Android典型界面设计——ViewPage+Fragment实现区域顶部tab滑动切换 一、问题描述   本系列将结合案例应用,陆续向大家介绍一些Android典型界面的设计,首先说说tab导航,导航分为一层和两层(底部区块+区域内头部导航),主要实现方案有RadioGroup+ViewPage+Fragment、Viewpager Indicator、ActionBar Tabs、FragmentTabHost+Fragment等,下面我们先采用RadioGroup+ 阅读详情

 

本文主要实现底部Tab的动态添加,动态添加图片、文字状态选择器,支持tab的本和和网络图片,支持各自Tab各自控制,支持Tab的隐藏和显示,非常灵活。实现原理是自定义RadioGroup+RadioButton,效果图如下:

关于小红点和角标实现参考上一篇文章介绍:

https://blog.youkuaiyun.com/yoonerloop/article/details/107589057

要实现单选效果RadioGroup包含的子View只能是RadioButton,不能为LinearLayout,为LinearLayout则单选效果和一系列的监听就失效了,要实现子View为LinearLayout的单选只能重写LinearLayout了,可以参考:https://www.cnblogs.com/over140/p/3795877.html,这里直接使用RadioButton实现。

一、xml定义

<?xml version="1.0" encoding="utf-8"?>
<com.tencent.weapps.view.AppRadioButton xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ab_btn"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:button="@null"
    android:singleLine="true"
    android:ellipsize="end"
    android:gravity="center"
    android:paddingTop="15dp"
    android:background="@android:color/transparent"
    android:textColor="@color/selector_tab_text"
    android:textSize="11sp" />

二、MyRadioGroup继承自RadioGroup动态添加

    private void initView() {
        if (list == null || list.isEmpty()) {
            setVisibility(GONE);
            return;
        }
        removeAllViews();
        setOrientation(HORIZONTAL);
        setVisibility(VISIBLE);
        //添加RadioButton
        for (int i = 0; i < list.size(); i++) {
            AppRadioButton radioButton = (AppRadioButton) LayoutInflater.from(getContext()).inflate(R.layout.item_tab, null);
            radioButton.setId(i);
            addView(radioButton);
        }
        //设置RadioButton属性
        for (int i = 0; i < getChildCount(); i++) {
            AppRadioButton radioButton = (AppRadioButton) getChildAt(i);
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) radioButton.getLayoutParams();
            layoutParams.weight = 1;
            layoutParams.width = 0;
            layoutParams.gravity = Gravity.CENTER;
            radioButton.setLayoutParams(layoutParams);
            if (i == 0 && !radioButton.isChecked()) {
                radioButton.setChecked(true);
            } else {
                radioButton.setChecked(false);
            }
            if (!TextUtils.isEmpty(color) && !TextUtils.isEmpty(selectedColor)) {
                radioButton.setTextColor(getCheckedColorStateList(selectedColor, color));
            }
        }
        if (!TextUtils.isEmpty(backgroundColor)) {
            setBackgroundColor(Color.parseColor(backgroundColor));
        }
    }

    //设置背景颜色的状态选择器
    public static ColorStateList getCheckedColorStateList(@NonNull String checkedColor, 
        @NonNull String unCheckedColor) {
        int[][] states = new int[][]{
                new int[]{-android.R.attr.state_checked}, // unchecked
                new int[]{android.R.attr.state_checked}  // checked
        };
        int[] colors = new int[]{
                Color.parseColor(checkedColor),
                Color.parseColor(unCheckedColor)
        };
        return new ColorStateList(states, colors);
    }

注意这里不能偷懒,把添加RadioButton和设置属性放在一块去了,否则无法控制文字和icon之间的间距,绘制过程出现问题,要分开进行。

三、设置icon和文字

    private void setData() {
        if (list == null || list.isEmpty()) {
            setVisibility(GONE);
            return;
        }
        for (int i = 0; i < getChildCount(); i++) {
            TabBean bean = list.get(i);
            AppRadioButton radioButton = (AppRadioButton) getChildAt(i);
            setRadioButton(radioButton, bean);
        }
    }

    private void setRadioButton(AppRadioButton radioButton, TabBean bean) {
        ViewUtils.setText(radioButton, bean.text);
        if (TextUtils.isEmpty(bean.iconPath)) {
            radioButton.setTextSize(16);
            return;
        } else {
            radioButton.setTextSize(11);
        }
        radioButton.setCompoundDrawablePadding(drawablePadding);
        StateListDrawable stateListDrawable = new StateListDrawable();
        if (!bean.iconPath.startsWith("http") && !bean.selectedIconPath.startsWith("http")) {
            try {
                InputStream open = getResources().getAssets().open(bean.iconPath);
                InputStream selectOpen = getResources().getAssets().open(bean.selectedIconPath);
                Drawable drawable = Drawable.createFromStream(open, null);
                Drawable selectDrawable = Drawable.createFromStream(selectOpen, null);
                stateListDrawable.addState(new int[]{-android.R.attr.state_checked}, drawable);
                stateListDrawable.addState(new int[]{android.R.attr.state_checked}, selectDrawable);
                stateListDrawable.setBounds(0, 0, drawableSize, drawableSize);
                radioButton.setCompoundDrawables(null, stateListDrawable, null, null);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        Glide.with(getContext()).load(bean.iconPath).error(R.drawable.shape_circle_tab_default).into(new SimpleTarget<Drawable>() {
            @Override
            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                if (resource == null) {
                    return;
                }
                stateListDrawable.addState(new int[]{-android.R.attr.state_checked}, resource);
                Glide.with(getContext()).load(bean.selectedIconPath).into(new SimpleTarget<Drawable>() {

                    @Override
                    public void onResourceReady(@NonNull Drawable selectResource, @Nullable Transition<? super Drawable> transition) {
                        if (selectResource == null) {
                            return;
                        }
                        stateListDrawable.addState(new int[]{android.R.attr.state_checked}, selectResource);
                        stateListDrawable.setBounds(0, 0, drawableSize, drawableSize);
                        radioButton.setCompoundDrawables(null, stateListDrawable, null, null);
                    }

                    @Override
                    public void onLoadFailed(@Nullable Drawable errorDrawable) {
                        super.onLoadFailed(errorDrawable);
                        resource.setBounds(0, 0, drawableSize, drawableSize);
                        radioButton.setCompoundDrawables(null, resource, null, null);
                    }
                });
            }

            @Override
            public void onLoadFailed(@Nullable Drawable errorDrawable) {
                super.onLoadFailed(errorDrawable);
                Log.d("TAG",iconPath加载失败:"+ bean.selectedIconPath);
            }
        });
    }

四、更新RadioGroup属性

    public void upRadioButton(TabBean bean, int index) {
        if (getChildCount() == 0 || bean == null) {
            return;
        }
        for (int i = 0; i < getChildCount(); i++) {
            if (index == i) {
                AppRadioButton radioButton = (AppRadioButton) getChildAt(i);
                setRadioButton(radioButton, bean);
            }
        }
    }

五、更新右上角角标

    /**
     * 更新小红点
     * @param index
     * @param isShow
     */
    public void showRedPoint(int index, boolean isShow) {
        for (int i = 0; i < getChildCount(); i++) {
            if (index == i) {
                AppRadioButton radioButton = (AppRadioButton) getChildAt(i);
                radioButton.setShowSmallDot(isShow);
            }
        }
    }
    /**
     * 更新文字
     * @param index
     * @param text
     * @param isShow
     */
    public void showRedText(int index, String text, boolean isShow) {
        for (int i = 0; i < getChildCount(); i++) {
            if (index == i) {
                AppRadioButton radioButton = (AppRadioButton) getChildAt(i);
                radioButton.setNumberDot(isShow, text);
            }
        }
    }

 

 

深入理解Android Tab之radiogroup+fragment实现 Fragment代表应用程序用户界面中的一块功能区域。它拥有自己的布局和行为,可以看作是一个mini activity。Fragment的使用可以让应用界面更加模块化,易于管理。它不是直接运行在Activity上,而是必须嵌入到Activity中使用。Fragment可以存在于一个活动的用户界面中,并且可以从一个Activity中附加或分离。这意味着可以根据用户的交互来动态地修改屏幕上的内容。Android允许开发者对底部导航栏进行高度定制,包括图标、文字、背景以及选中状态的动画效果。 阅读详情

相关推荐

Android fragment制作微信菜单界面

用fragment做的一个仿微信菜单的demo,有兴趣的可以下载下来看着学习一下!

RadioGroup动态添加RadioButton,并且获得事件

由于有许多的RadioButton是动态的,不是固定的一些,所以需要在代码中,动态的添加到RadioGroup中,下面是我的实现方法。 1、添加RadioButton到RadioGroup中 [java]  view plain copy RadioGroup group;  for(int i=0; i10; i++)  {      Radio

当富网络 1536

RadioGroup实现APP首页底部Tab的切换

RadioGroup实现APP首页底部Tab的切换,原文链接:http://www.cnblogs.com/smyhvae/p/4463931.html

Android中RadioGroup在代码中动态添加子控件RadioButton

如下图: 我用红线圈出的地方,这个地方想来还得在代码中动态生成,因为个数你不确定 下面看代码: import java.util.ArrayList; import java.util.List; import com.ss.b.helps.DensityUtilHelps; import android.app.Activity; import android.graphics.C

麦壳的记忆 2万+

动态添加RadioGroup的RadioButton.rar

动态添加RadioGroup的RadioButton.rar

Android实现购物车及其他功能的角标

本文主要介绍了Android实现购物车及其他功能的角标的相关知识。具有很好的参考价值。下面跟着小编一起来看下吧

RadioGroup中动态添加RadioButton

for (int i = 0; i < mDeliveryPayModeBeans.size(); i++) {//设置数量 RadioButton tempButton = new RadioButton(DeliveryDeliveredActivity.this);//this就是你的activity RadioGroup.LayoutParams lp = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, View

qq_28641023的博客 585

【多媒体交互】Unity+普通摄像头实现UI事件分析

利用摄像头捕捉用户的手势或动作,结合坐标映射与事件系统触发UI交互

qq_38350004的博客 1312

RadioButton小红点、数字角标的实现

RadioButton通常作为RadioGroup的子布局嵌套在里面,单独使用不太常用,本文实现RadioButton小红点、数字角标,主要是利用onDraw方法进行重写,绘制小红点、数字角标。如下: public class AppRadioButton extends AppCompatRadioButton { private Paint mPaint; private boolean isShowDot; private boolean isShowNumbe..

一杯清泉 1931

Nsight Compute内存图表实战:如何快速定位CUDA内核的内存瓶颈(附配置截图)

本文详细介绍了如何使用Nsight Compute的Memory Chart功能快速定位和诊断CUDA内核中的内存性能瓶颈。通过解析内存图表中的逻辑与物理单元节点、连线颜色含义,并结合实战案例(如低L1缓存命中率、共享内存Bank冲突、全局内存访问未合并),指导开发者从可视化数据回溯至源代码,进行精准有效的内存访问优化,从而提升GPU程序性能。

zeta9的博客 479

Kriging代理模型理论相关推导

代理模型,Kriging,加点准则

森屹的博客 1万+

Android新闻客户端(仿网易)--上

效果截图本来想找个软件动态截图,但是好像没找着。。。这样的话,看不出来点击之后的动态切换效果了。以后找着了再来替换。 [img]http://www.eoeandroid.com/data/attachment/forum/201212/25/135448umt5valrithrcvm9.png[/img][img]http://www.eoeandroid.com/data/attachm...

乐乐乖乖的博客 354

QGroundControl实现多机控制

前言 作为西安电子科技大学的本科生一名,目前在研究关于无人机导航规划与轨迹控制方面。 目前在跟导师做关于雷达无人机的一个项目,在这里记录一下关于QGC地面站实现多机控制的一些方法。 某些地方写的可能不是很完善,欢迎大家补充。 目前该文章还未写完,后期本人会继续编写 多机控制原理 多机地面站支持TCP,UDP和串口等三种连接方式,首先我们需要对这两种连接方式抽象出一个基类LinkInterface,提供两个虚函数分别对应于数据接受和发送处理,针对于不同的连接方式实现TCP,UDP和串口连接相对应的子类TCPL

Phillweston的博客 8426

Tab效果之radiogroup+fragment

今天第一次写boge

bzy601638015的专栏 903

多时间尺度源储荷微电网协调调度+日前日内实时+需求响应——附代码

为提高区域电网新能源消纳率,使电力系统运行成本最小,提高电力系统供电可靠性。提出考虑特性分布的储能电站接入的电网多时间尺度“源–储–荷”协调调度策略。综合储能电站、负荷侧各类需求响应资源的多时间尺度特性制定日前调度计划,并通过日内滚动与实时修正实现对预测数据更高精度的保证。以系统运行成本、弃风惩罚成本、失负荷惩罚成本为目标函数,建立多时间尺度调度模型。最后通过 MATLAB 平台调用商用软件包 CPLEX 完成混合整数规划优化,结果表明该调度策略可以达到系统运行成本最优,降低弃风率的效果。

不定时分享电力优化、神经网络、数学建模等技术等 6385

ComfyUI 局部重绘工作流示例

本文介绍了使用ComfyUI进行图像局部重绘的基础工作流程,重点讲解如何修改人物眼睛颜色和表情。主要内容包括:1.准备工作(可选下载DreamShaperv8模型);2.加载素材图片和工作流文件;3.使用遮罩编辑器绘制需要修改的区域;4.修改提示词控制生成内容;5.调整denoise参数优化效果。教程提供了详细的提示词示例(如"smile,blackeyes"等)和参数设置建议,帮助用户通过多次尝试获得理想效果。该工作流适用于修改图像局部区域而不影响整体画面。

云域A的博客 330

Android 动态切换底部tab按钮

身为一个Android开发人员,总是会遇到很多需求 直接上代码,代码里有注释,我使用的就是原生的radioGroup+radioButton public class IndexActivity extends AppCompatActivity { private RadioGroup index_rg_bottom; private RadioButton index_...

bigahua的博客 1433

Codex 接入国产大模型指南:客户端与 CLI 双端实战

CC Switch是目前最流行的 Codex / Claude Code 模型切换工具,内置了协议转换功能,支持几乎所有主流国产模型。核心原理Codex → 本地 8317 端口(CC Switch)→ 协议转换 → 国产模型 API整个过程对 Codex 完全透明,Codex 以为自己在跟标准的 Responses API 对话。用户类型推荐方案理由新手 / 不想折腾配置简单,免费额度够用追求稳定体验通义千问(原生接入)官方兼容,功能最完整企业用户自建 AI 网关可控性强,支持多用户管理预算有限。

篮球界最会写bug的人;程序猿中打球最菜的人。 571

Android 底部导航栏(底部Tab)最佳实践

本文目录.png 当开始一个新项目的时候,有一个很重要的步骤就是确定我们的APP首页框架,也就是用户从桌面点击APP 图标,进入APP 首页的时候展示给用户的框架,比如微信,展示了有四个Tab,分别对应不同的板块(微信、通讯录、发现、我),现在市面出了少部分的Material Design 风格的除外,大部分都是这样的一个框架,称之为底部导航栏,分为3-5个Tab不等。前段时间开始了一个

Be a valuable programmer 2万+

【思博伦】史上最详细Spirent TestCenter测试仪2544套件使用图文教程精讲!图解超赞超详细!!!

Avalanche测试仪使用指南 摘要:本文介绍了Avalanche测试仪的基本配置和使用方法。该测试仪采用Linux内核系统,通过端口模拟客户端与服务器端,支持HTTP、DNS、FTP等多种协议。文章详细讲解了管理IP配置、端口占用、项目创建、客户端/服务器端的参数设置(包括负载模拟、行为配置、网段设置等),以及测试执行和结果查看的全流程。特别针对HTTP测试,说明了测试前的组网准备和注意事项,包括IP地址规划、License申请等。同时提供了2544套件的时延和吞吐量测试方法,包括参数配置技巧和结果分析

风云说通信 2267

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android 多点触控 RadioGroup + Fragment 实现的底部Tab 能防止用户同时点击多个button而只响应一个有效事件吗?

Android底部导航栏(底部Tab)是一个Android程序员入门必须会实现的一个功能点,在Material Design(基于Android 5.0 API level 21)设计出来之前大家实现底部Tab通常会用FragmentTabHost或RadioGroup方式。而在有了 Android Support Library (com.android.support:design:xx.x...

huch的博客 927

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android底部tab导航栏中间凸起、动态配置替换底部导航栏Tab图标

Android底部tab导航栏中间凸起、动态配置替换底部导航栏Tab图标

weixin_38090079的博客 1570

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

安卓实现首页底部导航菜单中间图标凸起效果

效果图 1,Activity代码如下: public class ThirdActivity extends BaseActivity { @BindView(R.id.fl_layout) FrameLayout flLayout; @BindView(R.id.radioGroup) RadioGroup radioGroup; @BindView(...

智玲君 2901

通过RadioGroup组件实现微信底部的切换按钮(Tab》

<RadioGroup android:id="@+id/radiogroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" androi

ArchurSpace 590

底部导航栏点击跳转fragment

网上找了很多底部导航栏fragment切换,感觉各种方法都试了,下面是我自己整理的,希望能帮到大家。 (1)点击图片变色的xml文件写好。图片自己处理好。一个为例,其三个同理。 <selector xmlns:android="http://schemas.android.com/apk/res/android"> (2)layout布局文件的引用。

优快云YUANDAIMAXUEXI的博客 2176

通过TabActivity创建底部菜单栏

隐藏TabWidget,通过RadioGroup和RadioButton实现底部菜单栏,因为这种方法更灵活,界面更容易控制,geng

1103
上一篇: RadioButton小红点、数字角标的实现
下一篇: CameraX实现预览、拍照、录制视频
一杯清泉
博客等级 码龄11年 314粉丝 210原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值