一行代码实现vip标志的显示

需求说明

在项目中,后期添加了一种用户类型。需要再用户头像右下角显示一个vip的标志。问题是只要有头像的地方都要显示。而有头像的地方很多,设置到的接口也很多。后面考虑通过一个工具类,将这个功能外挂到原来的业务需要的地方。

实现效果

使用方式

  WzhVipView.show(ivAvatar,info);

效果如下,可以在不同大小的头像的右下角添加一个vip的标志还不影响原来的布局
在这里插入图片描述

实现原理

以下方法中,有两个参数。第一个是头像对应的控件,第二个是是否是特殊角色的javabean。
通过在ivAvatar外面包裹relativeLayout和添加一个显示vip图片的imageView来实现。第二个参数,通过反射获取其中的字段来判断是否需要显示vip标志。如果第二个参数是boolean类型的就直接用来控制vip标志的显示,兼容性更好。

  WzhVipView.show(ivAvatar,info);

相关代码

没什么难度,重点是对ivAvatar的父容器是RelativeLayout的情况下,替换以后。需要对兄弟控件的布局规则进行更新。为什么不直接把替换的布局的id设置为ivAvatar的id。因为在recycleView中。可能需要通过id来复用ivaAvatar。还有个需要注意的地方就是对ivAvatar没有宽高的时候的处理。通过添加监听器实现重新布局。最后还有个就是对反射的处理,需要通过递归的方式来判断第二个对象的父类中有没有需要的字段。提高代码的健壮性。

package com.trs.v8.wzh;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.trs.news.R;

import java.lang.reflect.Field;

/**
 * <pre>
 * Created by zhuguohui
 * Date: 2024/5/15
 * Time: 10:29
 * Desc:用来显示温州号顶部vip标志的
 * </pre>
 */
public class WzhVipView {


    /**
     * 根据是否是温州号来实现vip标志的显示
     *
     * @param headView 用户显示头像的view
     * @param obj      用户判断是否是温州号的javabean
     *                 通过判断其内部是否包含mediaAccountId字段,并且值不为空也不为0来实现
     *                 如果obj是boolean类型的,就直接作为是否是温州号的判断
     */
    public static void show(View headView, Object obj) {
        //wrap view,通过在headView的外部包裹RelativeLayout来实现
        ImageView vipView = wrapViewIfNeed(headView);
        boolean isVip = isWzh(obj);
        vipView.setVisibility(isVip ? View.VISIBLE : View.GONE);
    }

    private static boolean isWzh(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof Boolean) {
            return (boolean) obj;
        }
        try {
            Field idField = getFiled(obj.getClass());
            idField.setAccessible(true);
            Object idObj = idField.get(obj);
            if (idObj instanceof String) {
                String idStr = (String) idObj;
                if (!"".equals(idStr) && !"0".equals(idStr)) {
                    return true;
                }
            } else if (idObj instanceof Integer) {
                Integer idInt = (Integer) idObj;
                return idInt != 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    private static Field getFiled(Class clazz) {
        if (clazz == null || clazz == Object.class) {
            return null;
        }
        try {
            return clazz.getDeclaredField("mediaAccountId");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            return getFiled(clazz.getSuperclass());
        }
    }

    private static ImageView wrapViewIfNeed(View headView) {

        VipParentView wrapLayout = null;

        if (headView instanceof VipParentView) {
            wrapLayout = (VipParentView) headView;
        } else {

            ViewParent parent = headView.getParent();

            if (parent instanceof VipParentView) {
                wrapLayout = (VipParentView) parent;
            }
            if (wrapLayout == null) {
                //没有被适配过。开始适配
                wrapLayout = new VipParentView(headView.getContext());
                wrapLayout.setClipChildren(false);
                if (parent instanceof ViewGroup) {

                    //获取headView的宽高
                    int width = headView.getWidth();
                    if (width == 0) {
                        addListenerToReSizeVipView(headView, wrapLayout);
                    }
                    //根据宽高计算vip需要显示的宽高
                    int vipSize = (int) (width * 0.46);

                    ViewGroup group = (ViewGroup) parent;
                    group.setClipChildren(false);


                    ViewGroup.LayoutParams layoutParams = headView.getLayoutParams();
                    wrapLayout.setLayoutParams(layoutParams);
                    int index = group.indexOfChild(headView);
                    group.removeView(headView);
                    RelativeLayout.LayoutParams headParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT);
                    headParams.addRule(RelativeLayout.CENTER_IN_PARENT);
                    headView.setLayoutParams(headParams);
                    wrapLayout.addView(headView);


                    ImageView vipView = new ImageView(headView.getContext());
                    vipView.setImageResource(R.drawable.ic_header_vip);
                    vipView.setId(R.id.vip_view);

                    RelativeLayout.LayoutParams vipParams = new RelativeLayout.LayoutParams(vipSize, vipSize);
                    vipParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                    vipParams.addRule(RelativeLayout.ALIGN_PARENT_END);


                    vipView.setLayoutParams(vipParams);

                    wrapLayout.addView(vipView);

                    wrapLayout.setId(R.id.vip_parent_view);
                    updateRulesIfGroupIsRelativeLayout(group, headView.getId(), wrapLayout.getId());
                    group.addView(wrapLayout, index);

                } else {
                    return new ImageView(headView.getContext());
                }
            }
        }
        return (ImageView) wrapLayout.findViewById(R.id.vip_view);
    }

    private static void updateRulesIfGroupIsRelativeLayout(ViewGroup group, int headViewId, int wrapLayoutId) {
        if (!(group instanceof RelativeLayout)) {
            return;
        }
        int count = group.getChildCount();
        for (int i = 0; i < count; i++) {
            View childAt = group.getChildAt(i);
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) childAt.getLayoutParams();
            RelativeLayout.LayoutParams newLayoutPrams = new RelativeLayout.LayoutParams(layoutParams.width, layoutParams.height);
            newLayoutPrams.setMargins(layoutParams.leftMargin, layoutParams.topMargin,
                    layoutParams.rightMargin, layoutParams.bottomMargin);

            int[] rules = layoutParams.getRules();
            for (int j = 0; j < rules.length; j++) {
                if (rules[j] == headViewId) {
                    newLayoutPrams.addRule(j, wrapLayoutId);
                } else if (rules[j] != 0) {
                    newLayoutPrams.addRule(j, rules[j]);
                }
            }
            childAt.setLayoutParams(newLayoutPrams);
        }

    }


    private static void addListenerToReSizeVipView(View headView, RelativeLayout wrapLayout) {
        headView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int width = headView.getWidth();
                if (width == 0) {
                    return;
                }
                int vipSize = (int) (width * 0.46);
                View vipView = wrapLayout.findViewById(R.id.vip_view);
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) vipView.getLayoutParams();
                layoutParams.width = vipSize;
                layoutParams.height = vipSize;

                vipView.setLayoutParams(layoutParams);
                headView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });
    }

    private static class VipParentView extends RelativeLayout {

        public VipParentView(Context context) {
            super(context);
        }


    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/632085.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java—如何判断两个浮点数相等

结论 一旦有浮点型数据参与运算的结果&#xff0c;一定不要使用 “ ” 与其比较。 提出问题 我们知道在Java中浮点数float 和 double 的值不能很精准的表示一个小数&#xff0c;因为会有精度损失。 下面来看一个例子&#xff1a; public class FloatTest {public static …

教程:在 Apifox 中将消息通知集成到钉钉、飞书等应用

Apifox 支持将「消息通知」集成到第三方应用平台&#xff0c;包括企业微信、钉钉、飞书、Webhook 和 Jenkins。具体可在项目的【项目设置 -> 通知设置 -> 外部通知】里新建一个通知事件&#xff0c;然后在弹出的界面中配置即可。 在配置界面可以选择需要的触发事件&#…

如何在WordPress中启用两因素身份验证?

在WordPress中启用两因素身份验证方法&#xff1a;安装和激活WordFence安全性、启用两因素验证。 使用您可以从任何位置登录的任何门户&#xff0c;建议启用两个因素身份验证以增加帐户的安全性。 这样&#xff0c;即使有人可以正确猜测你的密码&#xff0c;它们仍然需要获得2…

诸葛智能携手五大银行,以数据驱动的营销中台带来可预见增长

对于银行来说&#xff0c;客户是赖以生存的基础&#xff0c;也是保持活力的关键。尤其是大数据、人工智能等新兴技术的推动下&#xff0c;通过数据赋能产品升级和服务创新&#xff0c;深挖客户潜能&#xff0c;更是助推银行快步迈入高质量发展的新阶段。 在银行加速拥抱新质生…

32位处理的寻址方式

32位处理器兼容16位处理器的寻址方式&#xff0c;可以运行传统的16位代码。但是由于32位的处理器都拥有32位的寄存器和算数逻辑部件&#xff0c;而且同内存芯片之间的数据通路至少是32位的&#xff0c;因此&#xff0c;所有需要从寄存器或者内存地址处取得操作数的指令都被扩充…

Python专题:八、为整数增加小数点

1、题目 虽说很多人讨厌小数点&#xff0c;但是有时候小数点是必不可少的一项&#xff0c;请你使用强制类型转换为输入的整数增加小数点&#xff0c;并输出改变类型后的变量类型。 2、代码 import sysa float(int(input())) print(f"(a:.lf)",type(a),sep"\…

RTMP低延迟推流

人总是需要压力才能进步, 最近有个项目, 需要我在RK3568上, 推流到公网, 最大程度的降低延迟. 废话不多说, 先直接看效果: 数据经过WiFi发送到Inenter的SRS服务器, 再通过网页拉流的. 因为是打金任务, 所以逼了自己一把, 把RTMP推流好好捋一遍. 先说说任务目标, 首先是MPP编码…

什么是检索增强生成(Retrieval Augmented Generation)?RAG 架构如何实现?

检索增强生成&#xff08;Retrieval Augmented Generation&#xff09;时代 在不断发展的生成人工智能世界中&#xff0c;检索增强生成 (RAG) 标志着一项重大进步&#xff0c;它将检索模型的准确性与生成模型的创造性相结合&#xff0c;达到了准确&创新的更高层级。 这种…

vue嵌套路由

一、嵌套 children配置 1.父类路由 mymusic 2.子类路由 musicson 1.创建MusicSon组件 <template><div><p>从前和后来</p><p>唯一</p><p>运气来的似有若无</p></div> </template><script>export defaul…

关于电源3(整流滤波电路)

整流滤波电路 框图 一共有四种整流电路 以下是自己参考别人的文章https://blog.csdn.net/zhuguanlin121/article/details/130653498?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171582622316800215096518%2522%252C%2522scm%2522%253A%252220140713.130102334…

【全开源】云界旅游微信小程序(源码搭建/上线/运营/售后/维护更新)

开启您的云端旅行新体验 一、引言 在快节奏的现代生活中&#xff0c;旅行成为了人们放松身心、探索世界的重要方式。让您的旅行更加便捷、高效&#xff0c;打造了云界旅游小程序&#xff0c;带您领略云端旅行的无限魅力。 二、小程序功能概览 云界旅游小程序集成了丰富的旅游…

SIP-7041 20W SIP广播网络有源音箱 校园广播20W木质SIP音箱

SIP-7041 20W SIP广播网络有源音箱 校园广播20W木质SIP音箱 一、描述 SIP-7041 20W SIP广播网络有源音箱 支持标准SIP协议 SIP-7041是我司的一款壁挂式网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到…

二三维战场仿真系统

收费工具&#xff0c;白嫖党勿扰 收费金额1万元 1 概述 给某个公司做了一个战场仿真系统&#xff0c;该公司给了5W的辛苦费。现在把相关功能部分提取出来&#xff0c;给需要的同学。 2 功能说明 战场仿真系统&#xff0c;分为三个部分&#xff1a; 服务器&#xff0c;用来发…

澳鹏Appen入选大模型产业链基础层图谱及案例研究

近日&#xff0c;由亿欧、上海市人工智能行业协会&#xff08;SAIA&#xff09;主办的2024全球开发者大会“百模大战”商业发展讲坛成功举办。作为全球开发者大会的平行技术论坛之一&#xff0c;本场论坛聚焦大模型产业&#xff0c;分析大模型赛道的竞争格局&#xff0c;洞悉大…

visual studio snippet常用注释片段

Visual Studio 2022 添加自定义代码片段_vs2022 代码片段-CSDN博客 dclass.snippet: <?xml version"1.0" encoding"utf-8"?> <CodeSnippets xmlns"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> …

Hello, GPT-4o!

2024年5月13日&#xff0c;OpenAI 在官网正式发布了最新的旗舰模型 GPT-4o 它是一个 多模态模型&#xff0c;可以实时推理音频、视频和文本。 * 发布会完整版视频回顾&#xff1a;https://www.youtube.com/watch?vDQacCB9tDaw GPT-4o&#xff08;“o”代表“omni”&#xff0c…

haddoop三大核心组件

hadoop三大核心组件分别是hdfs、mapreduce和yarn。 1、hdfs&#xff1a;即分布式文件系统&#xff0c;用于存储hadoop集群中的大量数据。具有高容错性&#xff0c;可跨多个数据节点存储数据&#xff0c;并提供高吞吐量的数据访问&#xff1b; 2、mapreduce&#xff1a;用于大…

Python代码:一、HelloWorld

1、题目&#xff1a; 将字符串 Hello World! 存储到变量str中&#xff0c;再使用print语句将其打印出来。 2、代码 import sys str Hello World ! print(str)3、在sublime运行的结果

IT行业的现状与未来发展趋势:重塑生活与工作的无限可能

随着科技的飞速发展&#xff0c;IT行业已经逐渐从幕后走到台前&#xff0c;成为推动全球经济和社会发展的核心动力。从云计算的普及、大数据的崛起&#xff0c;到人工智能的爆发&#xff0c;再到物联网、5G通信和区块链技术的日新月异&#xff0c;这些技术不仅正在深刻改变着我…

2024年抖店保证金交多少?保证金常见问题解答,一文解决你所有疑惑

大家好&#xff0c;我是电商花花 新手如果想要开抖音小店&#xff0c;有一个大坑是必须要避开的。 就是我们店铺开通之后&#xff0c;我们一定要交保证金&#xff0c;如果不交&#xff0c;那就是0元开店。 很多新手听别人说做抖音小店可以0元开店&#xff0c;不用缴纳保证金就…