Android 几个简单的自定义对话框介绍

news2025/5/26 2:05:53

Android 几个简单的自定义对话框介绍

文章目录

    • 一、前言
    • 二、对话框相关内容
      • 1、效果
      • 2、对话框显示的调用代码
        • (1)原生对话框代码:
        • (2)自定义对话框代码:
      • 3、对话框SweetAlertDialog 主要实现代码:
      • 4、优点和缺点
        • (1)优点
        • (2)缺点
        • (3)其他扩展
    • 三、其他
      • 1、小结
      • 2、Android对话框的使用总结
      • 3、Android加载中对话框示例

一、前言

Android 对话框直接使用肯定是不好看的,如果需要添加取消和确定按钮,肯定是需要进行自定义修改的。

本文简单介绍一个简单的可扩展的对话框,并且支持不同类型样式,加了点小动画。

有需要的可以看看。

二、对话框相关内容

1、效果

在这里插入图片描述

七个demo对话框显示,项目中可以根据实际情况进行使用。

原生对话框标题和内容是靠左的,如果显示默认的按钮是靠右下角的。

自定义的对话框则可以自己决定居中还是靠左和显示自己需要的图片。

2、对话框显示的调用代码

(1)原生对话框代码:
Dialog alertDialog = new AlertDialog.Builder(this).
    setTitle("对话框的标题").
    setMessage("对话框的内容").
    setIcon(R.drawable.ic_launcher).
    create();
alertDialog.show();

虽然 原生的AlertDialog 调用不复杂,但是显示有点丑,并且大小在不同设备上显示大小是不一样的。

AlertDialog 也是可以行决定是否显示确定和取消按钮的,监听setPositiveButton和setNegativeButton方法即可。

(2)自定义对话框代码:
 //(1)默认字符串显示,显示一个确认按钮,只是用来测试
 new SweetAlertDialog(this).show();
 
  //(2)修改标题和文本内容,显示一个确认按钮
 new SweetAlertDialog(this)
 .setTitleText("Title!")
 .setContentText("It's pretty, isn't it?")
 .show();
 
   //(3)修改标题和文本内容和类型图标,显示一个确认按钮
 new SweetAlertDialog(this, SweetAlertDialog.CUSTOM_IMAGE_TYPE)
 .setTitleText("Sweet!")
 .setContentText("Here's a custom image.")
 .setCustomImage(R.drawable.custom_img)
 .show();
 
 大部分场景上面三个代码比较常用。
 
 SweetAlertDialog 的类别,一种有五种,每种类别会选择不同的图标显示。
    public static final int NORMAL_TYPE = 0;
    public static final int ERROR_TYPE = 1;
    public static final int SUCCESS_TYPE = 2;
    public static final int WARNING_TYPE = 3;
    public static final int CUSTOM_IMAGE_TYPE = 4;
 
    //(4)修改标题和文本内容和类型图标,显示一个确认按钮,确定后执行相应的动作
 new SweetAlertDialog(this, SweetAlertDialog.SUCCESS_TYPE)
 .setTitleText("Good job!")
 .setContentText("You clicked the button!")
 .setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
         @Override
         public void onClick(SweetAlertDialog sDialog) {
         // reuse previous dialog instance
         Toast.makeText(SampleActivity.this, "confirm" ,Toast.LENGTH_SHORT).show();
         sDialog.dismiss();
        }
	})
.show();
 
    //(5)修改标题和文本内容和类型图标,点击第一次确定后,还要点一次确定
 new SweetAlertDialog(this, SweetAlertDialog.WARNING_TYPE)
 .setTitleText("Are you sure?")
 .setContentText("Won't be able to recover this file!")
 .setCancelText("No,cancel plx!")
 .setConfirmText("Yes,delete it!")
 .showCancelButton(true)
 .setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() {
     @Override
     public void onClick(SweetAlertDialog sDialog) {
         // reuse previous dialog instance
         sDialog.setTitleText("Cancelled!")
         .setContentText("Your imaginary file is safe :)")
         .setConfirmText("OK")
         .showCancelButton(false)
         .setCancelClickListener(null)
         .setConfirmClickListener(null)
         .changeAlertType(SweetAlertDialog.ERROR_TYPE);
         
        // or you can new a SweetAlertDialog to show

    }
})
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
    @Override
    public void onClick(SweetAlertDialog sDialog) {
        sDialog.setTitleText("Deleted!")
        .setContentText("Your imaginary file has been deleted!")
        .setConfirmText("OK")
        .showCancelButton(false)
        .setCancelClickListener(null)
        .setConfirmClickListener(null)
        .changeAlertType(SweetAlertDialog.SUCCESS_TYPE);
    }
})
.show();

项目中可以根据实际情况进行适配修改,显示一个按钮还是两个按钮都是可以选择的。

3、对话框SweetAlertDialog 主要实现代码:

package com.my.beautifuldialog;


import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Transformation;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class SweetAlertDialog extends Dialog implements View.OnClickListener {
    private View mDialogView;
    private AnimationSet mModalInAnim;
    private AnimationSet mModalOutAnim;
    private Animation mOverlayOutAnim;
    private Animation mErrorInAnim;
    private AnimationSet mErrorXInAnim;
    private AnimationSet mSuccessLayoutAnimSet;
    private Animation mSuccessBowAnim;
    private TextView mTitleTextView;
    private TextView mContentTextView;
    private String mTitleText;
    private String mContentText;
    private boolean mShowCancel;
    private String mCancelText;
    private String mConfirmText;
    private int mAlertType;
    private FrameLayout mErrorFrame;
    private FrameLayout mSuccessFrame;
    private SuccessTickView mSuccessTick;
    private ImageView mErrorX;
    private View mSuccessLeftMask;
    private View mSuccessRightMask;
    private Drawable mCustomImgDrawable;
    private ImageView mCustomImage;
    private Button mConfirmButton;
    private Button mCancelButton;
    private FrameLayout mWarningFrame;
    private OnSweetClickListener mCancelClickListener;
    private OnSweetClickListener mConfirmClickListener;
    private boolean mCanceledOnTouchOutside = false;

    public static final int NORMAL_TYPE = 0;
    public static final int ERROR_TYPE = 1;
    public static final int SUCCESS_TYPE = 2;
    public static final int WARNING_TYPE = 3;
    public static final int CUSTOM_IMAGE_TYPE = 4;

    public static interface OnSweetClickListener {
        public void onClick(SweetAlertDialog sweetAlertDialog);
    }

    public SweetAlertDialog(Context context) {
        this(context, NORMAL_TYPE);
    }

    public SweetAlertDialog(Context context, int alertType) {
        super(context, R.style.alert_dialog);
        setCancelable(true);
        setCanceledOnTouchOutside(false);
        mAlertType = alertType;
        mErrorInAnim = OptAnimationLoader.loadAnimation(getContext(), R.anim.error_frame_in);
        mErrorXInAnim = (AnimationSet)OptAnimationLoader.loadAnimation(getContext(), R.anim.error_x_in);
        // 2.3.x system don't support alpha-animation on layer-list drawable
        // remove it from animation set
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { //Android3 一下,其实没啥必要判断了
            List<Animation> childAnims = mErrorXInAnim.getAnimations();
            int idx = 0;
            for (;idx < childAnims.size();idx++) {
                if (childAnims.get(idx) instanceof AlphaAnimation) {
                    break;
                }
            }
            if (idx < childAnims.size()) {
                childAnims.remove(idx);
            }
        }
        mSuccessBowAnim = OptAnimationLoader.loadAnimation(getContext(), R.anim.success_bow_roate);
        mSuccessLayoutAnimSet = (AnimationSet)OptAnimationLoader.loadAnimation(getContext(), R.anim.success_mask_layout);
        mModalInAnim = (AnimationSet) OptAnimationLoader.loadAnimation(getContext(), R.anim.modal_in);
        mModalOutAnim = (AnimationSet) OptAnimationLoader.loadAnimation(getContext(), R.anim.modal_out);
        mModalOutAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mDialogView.setVisibility(View.GONE);
                mDialogView.post(new Runnable() {
                    @Override
                    public void run() {
                        SweetAlertDialog.super.dismiss();
                    }
                });
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        // dialog overlay fade out
        mOverlayOutAnim = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                WindowManager.LayoutParams wlp = getWindow().getAttributes();
                wlp.alpha = 1 - interpolatedTime;
                getWindow().setAttributes(wlp);
            }
        };
        mOverlayOutAnim.setDuration(120);
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.alert_dialog);
        mDialogView = getWindow().getDecorView().findViewById(android.R.id.content);
        mTitleTextView = (TextView)findViewById(R.id.title_text);
        mContentTextView = (TextView)findViewById(R.id.content_text);
        mErrorFrame = (FrameLayout)findViewById(R.id.error_frame);
        mErrorX = (ImageView)mErrorFrame.findViewById(R.id.error_x);
        mSuccessFrame = (FrameLayout)findViewById(R.id.success_frame);
        mSuccessTick = (SuccessTickView)mSuccessFrame.findViewById(R.id.success_tick);
        mSuccessLeftMask = mSuccessFrame.findViewById(R.id.mask_left);
        mSuccessRightMask = mSuccessFrame.findViewById(R.id.mask_right);
        mCustomImage = (ImageView)findViewById(R.id.custom_image);
        mWarningFrame = (FrameLayout)findViewById(R.id.warning_frame);
        mConfirmButton = (Button)findViewById(R.id.confirm_button);
        mCancelButton = (Button)findViewById(R.id.cancel_button);

        mConfirmButton.setOnClickListener(this);
        mCancelButton.setOnClickListener(this);

        setTitleText(mTitleText);
        setContentText(mContentText);
        showCancelButton(mShowCancel);
        setCancelText(mCancelText);
        setConfirmText(mConfirmText);
        changeAlertType(mAlertType, true);
//        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
    }

    private void restore () {
        mCustomImage.setVisibility(View.GONE);
        mErrorFrame.setVisibility(View.GONE);
        mSuccessFrame.setVisibility(View.GONE);
        mWarningFrame.setVisibility(View.GONE);

        mConfirmButton.setBackgroundResource(R.drawable.blue_button_background);
        mErrorFrame.clearAnimation();
        mErrorX.clearAnimation();
        mSuccessTick.clearAnimation();
        mSuccessLeftMask.clearAnimation();
        mSuccessRightMask.clearAnimation();
    }

    private void playAnimation () {
        if (mAlertType == ERROR_TYPE) {
            mErrorFrame.startAnimation(mErrorInAnim);
            mErrorX.startAnimation(mErrorXInAnim);
        } else if (mAlertType == SUCCESS_TYPE) {
            mSuccessTick.startTickAnim();
            mSuccessRightMask.startAnimation(mSuccessBowAnim);
        }
    }

    private void changeAlertType(int alertType, boolean fromCreate) {
        mAlertType = alertType;
        // call after created views
        if (mDialogView != null) {
            if (!fromCreate) {
                // restore all of views state before switching alert type
                restore();
            }
            switch (mAlertType) {
                case ERROR_TYPE:
                    mErrorFrame.setVisibility(View.VISIBLE);
                    break;
                case SUCCESS_TYPE:
                    mSuccessFrame.setVisibility(View.VISIBLE);
                    // initial rotate layout of success mask
                    mSuccessLeftMask.startAnimation(mSuccessLayoutAnimSet.getAnimations().get(0));
                    mSuccessRightMask.startAnimation(mSuccessLayoutAnimSet.getAnimations().get(1));
                    break;
                case WARNING_TYPE:
                    mConfirmButton.setBackgroundResource(R.drawable.red_button_background);
                    mWarningFrame.setVisibility(View.VISIBLE);
                    break;
                case CUSTOM_IMAGE_TYPE:
                    setCustomImage(mCustomImgDrawable);
                    break;
            }
            if (!fromCreate) {
                playAnimation();
            }
        }
    }

    public int getAlerType () {
        return mAlertType;
    }

    public void changeAlertType(int alertType) {
        changeAlertType(alertType, false);
    }


    public String getTitleText () {
        return mTitleText;
    }

    //解决dialog.setCanceledOnTouchOutside(true) 不生效问题
    public void setDialogTouchOutsideCloseable(Dialog dialog, int gravity) {
        Window window = dialog.getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.width = ViewGroup.LayoutParams.MATCH_PARENT;
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        window.setAttributes(params);
        window.setGravity(gravity);

    }

    //设置点击外部消失
    public SweetAlertDialog setCanceledOutside(boolean cancel) {
        setCanceledOnTouchOutside(cancel);
        return this;
    }

    //设置标题
    public SweetAlertDialog setTitleText (String text) {
        mTitleText = text;
        if (mTitleTextView != null && mTitleText != null) {
            mTitleTextView.setText(mTitleText);
        }
        return this;
    }

    //设置标题上方图标,Drawable 对象
    public SweetAlertDialog setCustomImage (Drawable drawable) {
        mCustomImgDrawable = drawable;
        if (mCustomImage != null && mCustomImgDrawable != null) {
            mCustomImage.setVisibility(View.VISIBLE);
            mCustomImage.setImageDrawable(mCustomImgDrawable);
        }
        return this;
    }

    //设置标题上方图标,Drawable int值
    public SweetAlertDialog setCustomImage (int resourceId) {
        return setCustomImage(getContext().getResources().getDrawable(resourceId));
    }

    public String getContentText () {
        return mContentText;
    }

    //设置显示内容
    public SweetAlertDialog setContentText (String text) {
        mContentText = text;
        if (mContentTextView != null && mContentText != null) {
            mContentTextView.setVisibility(View.VISIBLE);
            mContentTextView.setText(mContentText);
        }
        return this;
    }

    public boolean isShowCancelButton () {
        return mShowCancel;
    }

    //显示取消按钮
    public SweetAlertDialog showCancelButton (boolean isShow) {
        mShowCancel = isShow;
        if (mCancelButton != null) {
            mCancelButton.setVisibility(mShowCancel ? View.VISIBLE : View.GONE);
        }
        return this;
    }

    public String getCancelText () {
        return mCancelText;
    }

    //设置取消按钮的文字
    public SweetAlertDialog setCancelText (String text) {
        mCancelText = text;
        if (mCancelButton != null && mCancelText != null) {
            mCancelButton.setText(mCancelText);
        }
        return this;
    }

    public String getConfirmText () {
        return mConfirmText;
    }

    //设置确认按钮的文字
    public SweetAlertDialog setConfirmText (String text) {
        mConfirmText = text;
        if (mConfirmButton != null && mConfirmText != null) {
            mConfirmButton.setText(mConfirmText);
        }
        return this;
    }

    public SweetAlertDialog setCancelClickListener (OnSweetClickListener listener) {
        mCancelClickListener = listener;
        return this;
    }

    public SweetAlertDialog setConfirmClickListener (OnSweetClickListener listener) {
        mConfirmClickListener = listener;
        return this;
    }

    protected void onStart() {
        mDialogView.startAnimation(mModalInAnim);
        playAnimation();
    }

    public void dismiss() {
        mConfirmButton.startAnimation(mOverlayOutAnim);
        mDialogView.startAnimation(mModalOutAnim);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.cancel_button) {
            if (mCancelClickListener != null) {
                mCancelClickListener.onClick(SweetAlertDialog.this);
            } else {
                dismiss();
            }
        } else if (v.getId() == R.id.confirm_button) {
            if (mConfirmClickListener != null) {
                mConfirmClickListener.onClick(SweetAlertDialog.this);
            } else {
                dismiss();
            }
        }
    }
}

4、优点和缺点

(1)优点
显示方便UI好看
调用api简单方便
确定和取消按钮可以选择显示一个或者两个
添加了不同类别图标,并且图标会显示动画效果
扩展了点击一次确定后,还可以进行多次弹框的情况

(2)缺点
对话框显示的大小基本固定,适合简单信息的显示
对话框无法设置点击周边就消失,因为已经全局显示了
(3)其他扩展

可以用来做自定义Toast。

具体实现思路是:自定义几秒后,执行dismiss关闭对话框。

三、其他

1、小结

网上有千千万万中自定义对话框,各种花里胡哨的也很多,但是简单使用的很少。

在很多实际项目中只要用到demo代码中的最普通的显示文本的情况就ok的,需要显示图片的场景并不多。

并且上面显示图片类型的代码,都是添加了不同动画类的,移植反而麻烦。

所以一般的使用只移植简单文本部分的功能使用就OK了。

其他的就当预留的吧,万一真的要呢。

如果对话框UI没啥要求,只要可以显示文本和确定、取消按钮这样的场景,使用原生的AlertDialog很好了。

2、Android对话框的使用总结

都是对原生对话框的详细介绍

https://blog.csdn.net/wenzhi20102321/article/details/52818351

3、Android加载中对话框示例

转圈圈的加载中对话框

https://blog.csdn.net/wenzhi20102321/article/details/79619719

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在DAYU200上实现OpenHarmony跳转拨号界面

一、简介 日常生活中&#xff0c;打电话是最常见的交流方式之一&#xff0c;那么如何在OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;中进行电话服务相关的开发呢&#xff1f;今天我们可以一起来了解一下如何通过电话服务系统支持的API实现拨打电话的功能…

噱头还是风口?剖析AI短剧出海的未来

导语 |去年以来&#xff0c;低成本、高回报的土味短剧在国内爆火&#xff0c;而这股风也成功地刮到海外。2024 年&#xff0c;越来越多的人把目光投向了拥有庞大市场的国外“蓝海”&#xff0c;当人们还在高谈阔论 Sora 是否颠覆影视行业的时候&#xff0c;AI 已经在出海短剧中…

Linux系统搭建Tale个人博客网站并实现无公网IP访问本地博客

文章目录 前言1. Tale网站搭建1.1 检查本地环境1.2 部署Tale个人博客系统1.3 启动Tale服务1.4 访问博客地址 2. Linux安装Cpolar内网穿透3. 创建Tale博客公网地址4. 使用公网地址访问Tale 前言 今天给大家带来一款基于 Java 语言的轻量级博客开源项目——Tale&#xff0c;Tale…

【嵌入式芯片开发】不使用MicroLib的串口重定向万能预编译配置(适用于ARMCC、AC6等不同的编译器及版本)

【嵌入式芯片开发】不使用MicroLib的串口重定向万能预编译配置&#xff08;适用于ARMCC、AC6等不同的编译器及版本&#xff09; 文章目录 基本的串口重定向接收中断与scanf不能同时工作重定向卡死、低功耗一直唤醒 串口重定向万能预编译配置附录&#xff1a;Cortex-M架构的Sys…

【设计模式深度剖析】【5】【创建型】【原型模式】| 类比群发邮件,加深理解

&#x1f448;️上一篇:建造者模式 | 下一篇:创建型设计模式对比&#x1f449;️ 目录 原型模式(Prototype Pattern)概览定义英文原话直译 3个角色类图1. 抽象原型&#xff08;Prototype&#xff09;角色2. 具体原型&#xff08;Concrete Prototype&#xff09;角色3. 客户…

【cocos creator 】生成六边形地图

想要生成一个六边形组成的地图 完整代码示例 以下是完整的代码示例&#xff0c;包含了注释来解释每一步&#xff1a; cc.Class({extends: cc.Component,properties: {hexPrefab: {default: null,type: cc.Prefab},mapWidth: 10, // 网格的宽度&#xff08;六边形的数量&am…

基于Pytorch框架全连接神经网络对手势图片识别

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 手势识别是计算机视觉领域的一个重要研究方向&#xff0c;具有广泛的应用前景&#xff0c;如人…

react中怎么为props设置默认值

在React中&#xff0c;你可以使用ES6的类属性&#xff08;class properties&#xff09;或者函数组件中的默认参数&#xff08;default parameters&#xff09;来定义props的默认值。 1.类组件中定义默认props 对于类组件&#xff0c;你可以在组件内部使用defaultProps属性来…

基于Java的推箱子游戏设计与实现(论文 + 源码)

【免费】关于基于JAVA的推箱子游戏.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89325018 基于Java的推箱子游戏设计与实现 摘 要 社会在进步&#xff0c;人们生活质量也在日益提高。高强度的压力也接踵而来。社会中急需出现新的有效方式来缓解人们的压力。…

Java开发大厂面试第20讲:什么是分布式锁?Redi 怎样实现的分布式锁?

“锁”是我们实际工作和面试中无法避开的话题之一&#xff0c;正确使用锁可以保证高并发环境下程序的正确执行&#xff0c;也就是说只有使用锁才能保证多人同时访问时程序不会出现问题。 我们本课时的面试题是&#xff0c;什么是分布式锁&#xff1f;如何实现分布式锁&#xf…

秋招突击——算法打卡——5/24——无重复字符的最长字串

题目描述 实现代码 // 无重复字符的最长子串 int lengthOfLongestSubstring(string s) {int l 0,r 0;int res 0;unordered_map<char,int> temp;while(l < s.size()){temp[s.at(l)] l;for (r l 1; r < s.size() ; r) {if(temp.count(s.at(r))) break;else te…

Python UDP编程简单实例

TCP是建立可靠的连接&#xff0c;并且通信双方都可以以流的形式发送数据。 相对于TCP&#xff0c;UDP则是面向无连接的协议&#xff0c;不需要建立连接&#xff0c;只需要知道对方IP地址和端口号&#xff0c;就可以直接发送数据包。但是只管发送不保证到达。 虽然UDP传输数据…

详解 UML 中的关系概念

关联&#xff08;Association&#xff09; 表示两个类之间的一种语义性联系。例如: 学生与班级之间的关联关系。 有向关联&#xff08;Directed Association&#xff09; 关联关系有方向性,表示一个类能访问另一个类,但不一定反过来。例如: 教师能查看学生的成绩,但学生不能查…

三能一体运营体系助力政企支撑水平提升

生产力的发展是现代社会孜孜不倦的追求&#xff0c;由此产生了我们熟悉的“机械化、电子化、信息化”乃至现今正在发生的“智能化”四次工业革命。这些是由技术的突破性发展带来的&#xff0c;但我们也注意到生产力发展的另一个助力&#xff0c;即生产效率的提升&#xff0c;19…

PE文件(六)新增节-添加代码作业

一.手动新增节添加代码 1.当预备条件都满足&#xff0c;节表结尾没有相关数据时&#xff1a; 现在我们将ipmsg.exe用winhex打开&#xff0c;在节的最后新增一个节用于存放我们要增加的数据 注意&#xff1a;飞鸽的文件对齐和内存对齐是一致的 先判断节表末尾到第一个节之间…

系统架构师-考试-基础题-错题集锦1

系统架构师-考试-基础题-错题集锦 1.当一台服务器出现故障时将业务迁移到另外一台物理服务器上&#xff0c;保障了业务的连续性。 2.面向对象&#xff1a; 实体类&#xff0c;边界类&#xff0c;控制类 3.RUP&#xff1a;UP&#xff0c;统一过程&#xff0c;以架构为中心&am…

养鸡游戏牧场游戏已对接广告联盟功能介绍

养鸡游戏牧场游戏在对接广告联盟后&#xff0c;主要实现了以下几个功能&#xff1a; 广告展示与收益&#xff1a; 游戏内会嵌入广告联盟的广告&#xff0c;这些广告可能会以横幅、插屏、视频等多种形式出现在游戏的各个界面&#xff0c;如主界面、场景切换、任务完成等时机。广…

【深度学习02】注意力机制

1.自注意力机制 自注意力机制&#xff08;Self-Attention Mechanism&#xff09;是深度学习中的一种方法&#xff0c;广泛应用于自然语言处理和其他领域。为了更好地理解它&#xff0c;可以用一个简单的类比来解释。 类比&#xff1a;学生在课堂上做笔记 假设你是一个学生&a…

合约开发的基本结构剖析及前置知识梳理

前置知识点 上下文变量初步 合约函数的背后是transaction&#xff0c;上下文变量访问的是transaction中的信息两个上下文变量&#xff1a;tx和msg ERC20 规范代码实现Metamask测试 ganache-cli的安装 安装 npm install -g ganache-cli启动 ganache-cli如果出现以下这种…

ZooKeeper系列之ZAB协议

概述 ZooKeeper Atomic Broadcast&#xff0c;ZooKeeper原子消息广播协议。ZAB协议是为分布式协调服务ZK专门设计的一种支持崩溃恢复的原子广播协议。ZK主要依赖ZAB协议来实现分布式数据的最终一致性&#xff0c;基于该协议&#xff0c;ZK实现一种主备模式的系统架构来保持集群…