Android 纵向双选日历

news2024/11/25 10:29:36

这个日历的布局分两部分,一部分是显示星期几的LinearLayout,另外就是一个RecyclerView,负责纵向滚动了。

纵向双选日历

工具类:

implementation 'com.blankj:utilcode:1.17.3'

上activity_calendar代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="5dp"
            android:text="" />

    </LinearLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never" />
</LinearLayout>

接下来是CalendarActivity

  1. 计算数据
  2. 可以扩展日历的点击事件和范围选择事件
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.blankj.utilcode.constant.TimeConstants;
import com.blankj.utilcode.util.TimeUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

public class CalendarActivity extends AppCompatActivity {


    private RecyclerView recyclerView;

    private CalendarRangeAdapter calendarRangeAdapter;

    /**
     * 最大月份数
     */
    private int maxMonth = 12;

    private List<DateBean> dateList = new ArrayList<>();

    private List<DateBean> allDateList = new ArrayList<>();


    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            initView();
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calendar);

        recyclerView = findViewById(R.id.recycler_view);

        new Thread() {
            @Override
            public void run() {
                initData();
            }

            ;
        }.start();

    }

    private void initView() {
        GridLayoutManager manager = new GridLayoutManager(CalendarActivity.this, 7);
        manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return allDateList.get(position).getType() == 0 ? 7 : 1;
            }
        });
        recyclerView.setLayoutManager(manager);
        calendarRangeAdapter = new CalendarRangeAdapter(CalendarActivity.this, allDateList);
        recyclerView.setAdapter(calendarRangeAdapter);
        calendarRangeAdapter.setOnItemSelect(new CalendarRangeAdapter.OnItemSelect() {
            @Override
            public void onItemClick(int position) {

            }


            @Override
            public void onItemRangeSelect(String startDate, String endDate) {
                System.out.println(startDate + "~" + endDate);
            }
        });
    }

    private void initData() {
        for (int i = 0; i < maxMonth; i++) {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, i);

            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH) + 1;

            int maxDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
            String dateString = simpleDateFormat.format(calendar.getTime());

            DateBean monthBean = new DateBean();
            monthBean.setDate(dateString.substring(0, 7));
            monthBean.setCanSelect(false);
            monthBean.setType(0);

            dateList.clear();
            dateList.add(monthBean);

            calendar.set(Calendar.DAY_OF_MONTH, 1);

            //当月第一天是周几 0是周日,1是周一 以此类推
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
            //填充1号前面的空白
            for (int j = 0; j < dayOfWeek - 1; j++) {
                DateBean dateBean = new DateBean();
                dateBean.setCanSelect(false);
                dateBean.setType(1);
                dateBean.setDate("");
                dateList.add(dateBean);
            }

            for (int j = 0; j < maxDays; j++) {
                DateBean dateBean = new DateBean();
                dateBean.setType(1);
                dateBean.setCenterString(String.valueOf(j + 1));
                dateBean.setSelect(true);
                dateBean.setDate(year + "-" + addZero(month) + "-" + addZero(j + 1));
                //今天之前不可选中
                if (TimeUtils.getTimeSpanByNow(dateBean.getDate()
                        , new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
                        , TimeConstants.DAY) < 0) {
                    dateBean.setCenterString(String.valueOf(j + 1));
                    dateBean.setCanSelect(false);
                } else {
                    if (TimeUtils.getTimeSpanByNow(dateBean.getDate()
                            , new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
                            , TimeConstants.DAY) > 0) {
                        dateBean.setCenterString(String.valueOf(j + 1));
                    } else {
                        dateBean.setCenterString("今天");
                    }
                    dateBean.setCanSelect(true);
                }
                dateList.add(dateBean);
            }

            allDateList.addAll(dateList);
        }

        Message msg = handler.obtainMessage();
        handler.sendMessage(msg);

    }

    private String addZero(int text) {
        if (text < 10) {
            return "0" + text;
        } else {
            return "" + text;
        }
    }
}

上CalendarRangeAdapter代码(根据bean属性操作):

  1. 根据类型,填充月布局和日布局。
  2. 包含点击、范围选择的方法
public class CalendarRangeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context context;

    private List<DateBean> list;

    private int[] selectRange = new int[2];


    private final int TYPE_MONTH = 0;
    private final int TYPE_DAY = 1;

    public CalendarRangeAdapter(Context context, List<DateBean> list) {
        this.context = context;
        this.list = list;
        initSelect();
    }

    public void initSelect() {
        clearSelect();
    }


    public void clearSelect() {
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setSelect(false);
            list.get(i).setSelectRange(false);
            list.get(i).setBottomString("");
        }

        selectRange[0] = -1;
        selectRange[1] = -1;

    }

    public void notifySelect() {
        notifyDataSetChanged();
    }


    public void setData(List<DateBean> list) {
        this.list = list;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        RecyclerView.ViewHolder holder = null;
        if (viewType == 0) {
            //月份
            View view = LayoutInflater.from(context).inflate(R.layout.item_month,
                    parent, false);
            holder = new MonthViewHolder(view);
        } else {
            //日期
            View view = LayoutInflater.from(context).inflate(R.layout.item_day,
                    parent, false);
            holder = new DayViewHolder(view);
        }
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

        final int fPosition = holder.getAdapterPosition();
        if (holder instanceof MonthViewHolder) {
            ((MonthViewHolder) holder).tvMonth.setText(list.get(position).getDate().replace("-", "年") + "月");
        } else {
            final DayViewHolder viewHolder = (DayViewHolder) holder;

            viewHolder.tvCenter.setText(list.get(fPosition).getCenterString());
            viewHolder.tvBottom.setText(list.get(fPosition).getBottomString());
            if (viewHolder.llDay.getTag() instanceof View.OnClickListener){
                viewHolder.llDay.setOnClickListener( null);
            }
            if (list.get(fPosition).isCanSelect()) {
                //今天之前(不可选)
                if (TimeUtils.getTimeSpanByNow(list.get(position).getDate()
                        , new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
                        , TimeConstants.DAY) < 0) {
                    viewHolder.tvCenter.setTextColor(
                            ContextCompat.getColor(context, R.color.color_calendar_can_not_select));
                } else {
                    if (TimeUtils.getTimeSpanByNow(list.get(position).getDate()
                            , new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
                            , TimeConstants.DAY) > 0) {
                        viewHolder.tvCenter.setTextColor(
                                ContextCompat.getColor(context, R.color.color_calendar_can_select));
                    } else {
                        viewHolder.tvCenter.setTextColor(
                                ContextCompat.getColor(context, R.color.color_calendar_today));
                    }
                    if (list.get(fPosition).isSelect()) {
                        viewHolder.llDay.setBackgroundColor(
                                ContextCompat.getColor(context, R.color.color_calendar_background_select));
                        viewHolder.tvCenter.setTextColor(
                                ContextCompat.getColor(context, R.color.color_calendar_select));
                        viewHolder.tvBottom.setTextColor(
                                ContextCompat.getColor(context, R.color.color_calendar_select));
                    } else if (list.get(fPosition).isSelectRange()) {
                        viewHolder.llDay.setBackgroundColor(
                                ContextCompat.getColor(context, R.color.color_calendar_background_select_range));
                        viewHolder.tvCenter.setTextColor(
                                ContextCompat.getColor(context, R.color.color_calendar_select));
                        viewHolder.tvBottom.setTextColor(
                                ContextCompat.getColor(context, R.color.color_calendar_select));
                    } else {
                        viewHolder.llDay.setBackgroundColor(
                                ContextCompat.getColor(context, R.color.color_calendar_background_normal));
                    }


                    if (onItemSelect != null) {
             
                     View.OnClickListener clickListener =    new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                if (selectRange[0] == -1 && selectRange[1] == -1) {
                                    selectRange[0] = fPosition;
                                    list.get(fPosition).setSelect(true);
                                    list.get(fPosition).setBottomString("开始");
                                    onItemSelect.onItemClick(fPosition);
                                    notifyDataSetChanged();

                                } else if (selectRange[0] != -1 && selectRange[1] == -1) {
                                    onItemSelect.onItemClick(fPosition);
                                    if (fPosition < selectRange[0]) {
                                        clearSelect();
                                        selectRange[0] = fPosition;
                                        list.get(fPosition).setSelect(true);
                                        list.get(fPosition).setBottomString("开始");
                                    } else if (fPosition > selectRange[0]) {
                                        selectRange[1] = fPosition;
                                        list.get(fPosition).setSelect(true);
                                        list.get(fPosition).setBottomString("结束");
                                        for (int i = selectRange[0] + 1; i < selectRange[1]; i++) {
                                            list.get(i).setSelectRange(true);
                                            list.get(i).setBottomString("");
                                        }
                                        onItemSelect.onItemRangeSelect(list.get(selectRange[0]).getDate(), list.get(selectRange[1]).getDate());
                                    } else {
                                        clearSelect();
                                    }
                                    notifyDataSetChanged();
                                } else {
                                    clearSelect();
                                    selectRange[0] = fPosition;
                                    list.get(fPosition).setSelect(true);
                                    list.get(fPosition).setBottomString("开始");
                                    onItemSelect.onItemClick(fPosition);
                                    notifyDataSetChanged();
                                }
                            }
                        };
                        viewHolder.llDay.setOnClickListener(clickListener);
                        viewHolder.llDay.setTag(clickListener);
                    }

                }

            } else {
                viewHolder.llDay.setBackgroundColor(ContextCompat.getColor(context, R.color.color_calendar_background_normal));
                viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_can_not_select));
            }
        }
    }

    public OnItemSelect onItemSelect;


    public void setOnItemSelect(OnItemSelect onItemSelect) {
        this.onItemSelect = onItemSelect;
    }

    public interface OnItemSelect {
        void onItemClick(int position);

        void onItemRangeSelect(String startDate, String endDate);
    }

    @Override
    public int getItemViewType(int position) {

        return list.get(position).getType() == 0 ? TYPE_MONTH : TYPE_DAY;
    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }


    class MonthViewHolder extends RecyclerView.ViewHolder {
        TextView tvMonth;

        public MonthViewHolder(View itemView) {
            super(itemView);
            tvMonth = itemView.findViewById(R.id.tv_month);
        }
    }

    class DayViewHolder extends RecyclerView.ViewHolder {
        LinearLayout llDay;
        TextView tvCenter;
        TextView tvBottom;

        public DayViewHolder(View itemView) {
            super(itemView);
            llDay = itemView.findViewById(R.id.ll_day);
            tvCenter = itemView.findViewById(R.id.tv_center);
            tvBottom = itemView.findViewById(R.id.tv_bottom);
        }
    }
}

DateBean代码(中间文字,底部文字,是否可选等属性):

public class DateBean {

    /**
     * 日期
     */
    private String date;
    /**
     * 底部文字
     */
    private String bottomString;
    /**
     * 中间文字
     */
    private String centerString;

    /**
     * 是否可以选择
     */
    private boolean canSelect;
    /**
     * 是否选中
     */
    private boolean isSelect;

    /**是否在选中范围*/
    private boolean isSelectRange;
    /**
     * item type 0月份 1日期
     */
    private int type;


    public String getDate() {
        return date == null ? "" : date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getCenterString() {
        return centerString == null ? "" : centerString;
    }

    public void setCenterString(String centerString) {
        this.centerString = centerString;
    }

    public boolean isCanSelect() {
        return canSelect;
    }

    public void setCanSelect(boolean canSelect) {
        this.canSelect = canSelect;
    }

    public boolean isSelect() {
        return isSelect;
    }

    public void setSelect(boolean select) {
        isSelect = select;
    }

    public boolean isSelectRange() {
        return isSelectRange;
    }

    public void setSelectRange(boolean selectRange) {
        isSelectRange = selectRange;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getBottomString() {
        return bottomString == null ? "" : bottomString;
    }

    public void setBottomString(String bottomString) {
        this.bottomString = bottomString;
    }
}

上color.xml(可以自己换):

<resources>
    <color name="color_calendar_can_not_select">#dedede</color>
    <color name="color_calendar_can_select">#505050</color>
    <color name="color_calendar_select">#ffffff</color>
    <color name="color_calendar_today">#F67332</color>
    <color name="color_calendar_background_select">#F3BE30</color>
    <color name="color_calendar_background_select_range">#7DF3BE30</color>
    <color name="color_calendar_background_normal">#00000000</color>
</resources>

OK,完毕!

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

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

相关文章

Springboot+Vue项目-基于Java+MySQL的在线视频教育平台系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

中仕公考:非师范生能考教师编吗?

非师范生能考教师编吗?关于这个问题&#xff0c;首要条件是必须持有教师资格证。只要符合招聘条件&#xff0c;非师范专业背景的考生同样有资格报名参加教师编制考试。具体要求如下&#xff1a; 1. 年龄要求&#xff1a;申请人需年满35岁以下&#xff0c;对于特定职位&#x…

Elastic 线下 Meetup 将于 2024 年 4 月 27 号在重庆举办

2024 Elastic Meetup 重庆站活动&#xff0c;由 Elastic、新智锦绣联合举办&#xff0c;现诚邀广大技术爱好者及开发者参加。 活动时间 2024年4月27日 13:30-18:00 活动地点 中国重庆 沙坪坝区学城大道62-1号研发楼一期b3栋1楼(瑞幸咖啡旁&#xff09; 活动流程 14:00-14:50…

多因子模型的数据处理

优质博文&#xff1a;IT-BLOG-CN 数据处理的基本目的是从多量的、可能是杂乱无章的、难以理解的数据中抽取并推导出有价值、有意义的数据。特别是金融数据&#xff0c;存在数据缺失&#xff0c;不完整以及极端异常值等问题&#xff0c;对于我们的分析和建模影响很多。 对于我…

【新版HI3559AV100开发注意事项(四)】

新版HI3559AV100开发注意事项&#xff08;四&#xff09; 三十、HI3559A参数中对输入分辨率限制的原因是&#xff1f; 答&#xff1a;分辨率限制有两个来源&#xff1a; 一个是时钟频率最高为600M&#xff0c;开启一拍两像素之后相当于1200M。你这个数据量太大了&#xff0c;6…

(学习日记)2024.04.17:UCOSIII第四十五节:中断管理

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

微信小程序开发学习笔记——4.9【小案例】开启下拉刷新页面enablePullDownRefresh

>>跟着b站up主“咸虾米_”学习微信小程序开发中&#xff0c;把学习记录存到这方便后续查找。 课程连接&#xff1a;4.9.【小案例】开启下拉刷新页面enablePullDownRefresh_哔哩哔哩_bilibili 一、api2.json 小程序配置 / 页面配置 (qq.com) {"usingComponents&q…

抖音小店是什么?个人店、个体店、企业店,新手商家该如何选择?

大家好&#xff0c;我是电商花花。 抖音小店这两年来说都是一个发展不错的电商项目&#xff0c;凭借着直播电商的快速发展&#xff0c;让更多人看到了抖音小店其中的红利&#xff0c;吸引着商家入驻。 抖音小店是什么&#xff1f; 很多人会把抖音小店和达人橱窗搞混&#xff…

Harmony鸿蒙南向驱动开发-Regulator接口使用

功能简介 Regulator模块用于控制系统中某些设备的电压/电流供应。在嵌入式系统&#xff08;尤其是手机&#xff09;中&#xff0c;控制耗电量很重要&#xff0c;直接影响到电池的续航时间。所以&#xff0c;如果系统中某一个模块暂时不需要使用&#xff0c;就可以通过Regulato…

LC 515.在每个树行中找最大值

515. 在每个树行中找最大值 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9] 示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3] 提示&#xff1a; 二叉树的节点个数的范围是…

ubuntu下NTFS分区无法访问挂载-解决办法!

Ubuntu系统下&#xff0c;有的时候发现&#xff0c;挂载的NTFS文件系统硬盘无法访问。点击弹出类似问题&#xff1a; Error mounting /dev/sda1 at /media/root/新加卷: Command-line mount -t "ntfs" -o "uhelperudisks2,nodev,nosuid,uid0,gid0" "/…

LeetCode-416. 分割等和子集【数组 动态规划】

LeetCode-416. 分割等和子集【数组 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;01背包问题&#xff0c;动规五部曲解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分…

云计算:OVS 集群 使用 Geneve 流表

目录 一、实验 1.环境 2.OVS 集群 使用 Geneve 流表 二、问题 1.VXLAN与Geneve区别 一、实验 1.环境 (1) 主机 表1 宿主机 主机架构软件IP网卡备注ovs_controller控制端 karaf 0.7.3 192.168.204.63 1个NAT网卡 &#xff08;204网段&#xff09; 已部署ovs_server01服务…

【无标题】nodejs+mogoodb数据库写注册接口

描述 本篇文章主要记录使用nodejs express搭建服务器&#xff0c;并链接mogoodb数据来书写简单的后台接口&#xff1b;前端项目使用的vue2的一个酒店管理项目。阅读本文章&#xff0c;可以了解如何连接mogoodb数据库&#xff0c;和一些对数据库进行操作的命令。前端如何进行跨…

2024年Mathorcup数学建模竞赛A题思路

可以关注下&#xff0c;代码已出 【金山文档 | WPS云文档】 2024年Mathorcup思路代码在线文档https://link.zhihu.com/?targethttps%3A//kdocs.cn/l/cdlol5FlRAdE 整体来说这个题就两个步骤&#xff0c;第一是训练一个响应面模型&#xff0c;输入是附表1邻区的PCI值&#xff0…

裸机开发之汇编、寄存器

一、什么是汇编&#xff1f;为什么学汇编&#xff1f; 在之前写控制代码的时候就在想&#xff1a;底层是怎么控制的&#xff1f;后来经过学习知道之前所编写的代码都是应用层代码&#xff0c;顾名思义就是在系统写好的底层之上调用系统函数。原以为底层是指写系统写好的底层函数…

gitlab使用

个人笔记&#xff08;整理不易&#xff0c;有帮助&#xff0c;收藏点赞评论&#xff0c;爱你们&#xff01;&#xff01;&#xff01;你的支持是我写作的动力&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 个人随笔…

在线客服业务架构:构建智能互动与个性化服务

随着数字化时代的到来&#xff0c;在线客服业务正成为企业与客户沟通互动的重要渠道。在这个快节奏的时代&#xff0c;如何构建一个高效、智能的在线客服业务架构成为了企业关注的焦点。本文将探讨在线客服业务架构的重要性&#xff0c;并介绍如何构建智能互动与个性化服务的在…

自建远程桌面服务器,控制免root安卓手机和pc

RustDesk是一个开源的远程桌面软件&#xff0c;它允许用户通过互联网在不同设备之间共享桌面和控制权限。这款软件以最少的配置提供了自托管和安全保障&#xff0c;是一个类似于TeamViewer的开源替代品​ (RustDesk)​。RustDesk支持在Windows、macOS、Linux、iOS、Android以及…

图片合成二维码怎么实现?图片二维码的生成技巧

图片合成二维码如何制作呢&#xff1f;现在很多的二维码都会提供图片预览的功能&#xff0c;我们可以用手机扫描二维码来查看图片的信息&#xff0c;比如很多的产品信息、旅游攻略、产品海报等等类型经常会制作这种类型的二维码。 其实图片制作二维码的方法很简单&#xff0c;…