打造一个通用的TitleView

Android 灵活的自定义顶部标题栏 灵活的Android顶部标题栏,支持传入type值来控制顶部标题栏的控件的显示与隐藏,直接在布局引入就可以 立即下载

在开发应用的过程中,大部分应用应该都是有标题栏的。通常情况下,我们所使用的标题栏的高度什么其他设置之类的基本上都是相同。so,为了节省开发的效率,今天我们共同打造一个通用的标题栏。

  • 一般刚开发的时候,我们会有好几种情况去写标题栏,感觉刚入行的话,可能会在每个布局里面都去复制重复的布局,升级一点的话,应该会用include去把这个同样的布局,引入的主布局中。但是我感觉上面的方法都麻烦了。现在用一个自定义布局,只需要在布局中设置自己想要的东西就可以。那现在就让我们一起开始吧。
  • 首先展示一下我们经常的使用布局的一个样式,一般情况下都是有三个主要部分组成,第一个是返回按钮,一般都是有的,然后中间是说明这个页面的大概描述,最后一个是点击这个按钮可以跳转其他的页面之类的。这里写图片描述
  • 自定义View的话,有很多种情况,在这里我们使用继承原有的View实现自定义(其实是很简单的自定义了)。首先需要写一个布局,其实这个布局很简单的,就是我们平常用xml写的布局,不作具体介绍了。代码如下
<?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="wrap_content"
              android:background="@color/main_color"
              android:orientation="vertical">


    <RelativeLayout
        android:id="@+id/ll_root"
        android:layout_width="match_parent"
        android:layout_height="@dimen/common_title_height"
        android:background="@color/main_color">

        <LinearLayout
            android:clickable="true"
            android:id="@+id/btn_left"
            android:layout_width="@dimen/common_title_height"
            android:layout_height="match_parent"
            android:background="@drawable/selector_btn_back"
            android:gravity="center"
            android:padding="10dp">

            <ImageView
                android:id="@+id/left_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/ic_back_white"/>
        </LinearLayout>


        <TextView
            android:id="@+id/title_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:maxLength="20"
            android:maxLines="1"
            android:text="标题"
            android:textColor="@color/white"
            android:textSize="@dimen/title_text_size"/>

        <LinearLayout
            android:clickable="true"
            android:id="@+id/btn_right"
            android:layout_width="@dimen/common_title_height"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:background="@drawable/selector_btn_back"
            android:gravity="center"
            android:padding="10dp">

            <ImageView
                android:id="@+id/right_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/actionbar_menu"/>
        </LinearLayout>

    </RelativeLayout>

</LinearLayout>
  • 接下来就要自定义布局了,在这里我们继承LinearLayout来实现自定义View。只需要把下面属性复制到attrs.xml里面就行。这里面可能有点难的主要有两点吧,一个自定义属性,第二个就是点击事件之类的。
    1. 自定义属性:这里的话,我一共设置了九个自定义属性。其中要说的明的是最后两个属性里面有一个逻辑就是当左边的icon不显示的时候,不响应点击事件。同理右边的也是。
nameformat意义
title_colorcolor标题的背景颜色
title_text_sizedimension标题字体的大小
title_text_colorcolor标题字体的颜色
title_textstring标题字体的内容
title_left_iconreference标题左边的icon
title_right_iconreference标题右边的icon
title_highdimension标题栏的高度
left_isVisableboolean是否显示左边的icon
right_isVisableboolean是否显示右边的icon
<!--自定义标题栏-->
    <declare-styleable name="MyTitle">
        <attr name="title_color" format="color" />
        <attr name="title_text_size" format="dimension" />
        <attr name="title_text_color" format="color" />
        <attr name="title_text" format="string" />
        <attr name="title_left_icon" format="reference" />
        <attr name="title_right_icon" format="reference" />
        <attr name="title_high" format="dimension" />
        <attr name="left_isVisable" format="boolean" />
        <attr name="right_isVisable" format="boolean" />
    </declare-styleable>
  • 好了自定义属性设定好了,接下来就要写自定义view了。其实下面这段代码很简单,主要就是获取自定义属性,然后在代码里面设置就好了,感觉没什么好说的。
package com.mars.community.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.mars.community.R;


/**
 * @date 创建时间: 2017/12/2  21:46
 * @author zh_legendd
 * @Description 自定义的titleView
 * @Email code_legend@163.com
 * @Version 1.0
 */

public class TitleView extends LinearLayout {

    //标题的颜色
    private int title_color;
    //字体的大小
    private float title_text_size;
    //字体的颜色
    private int title_text_color;
    //字体内容
    private String title_text;
    //标题左边的icon


    private int title_left_icon;
    //标题右边的icon
    private int title_right_icon;
    //标题栏的高度
    private float title_high;
    //是否显示左边的icon
    private boolean left_isvisalbe;
    //是否显示右边的icon
    private boolean right_isvisalbe;
    //标题
    private TextView titleName;
    // 返回按钮控件
    private LinearLayout btnLeft;
    // 更多按钮控件
    private LinearLayout btnRight;
    // 返回按钮图标
    private ImageView leftIcon;
    // 更多按钮图标
    private ImageView rightIcon;
    //设置背景颜色
    private RelativeLayout ll_root;

    public TitleView(Context context) {
        this(context, null);
    }

    public TitleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TitleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.common_titile, this);
        //初始化视图
        initView();
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyTitle, defStyleAttr, 0);
        try {
            title_color = typedArray.getColor(R.styleable.MyTitle_title_color, ContextCompat.getColor(context, R.color.main_color));
            title_text_color = typedArray.getColor(R.styleable.MyTitle_title_text_color, ContextCompat.getColor(context, R.color.white));
            title_high = typedArray.getDimension(R.styleable.MyTitle_title_high, getResources().getDimension(R.dimen.common_title_height));
            title_text = typedArray.getString(R.styleable.MyTitle_title_text);
            title_left_icon = typedArray.getResourceId(R.styleable.MyTitle_title_left_icon, R.mipmap.ic_back_white);
            title_right_icon = typedArray.getResourceId(R.styleable.MyTitle_title_right_icon, 0);
//            title_text_size = typedArray.getDimension(R.styleable.MyTitle_title_text_size,getResources().getDimension(R.dimen.title_text_size));
            left_isvisalbe = typedArray.getBoolean(R.styleable.MyTitle_left_isVisable, true);
            right_isvisalbe = typedArray.getBoolean(R.styleable.MyTitle_right_isVisable, false);
            //设置内容
            titleName.setText(title_text);
//            titleName.setTextSize(dp2px(title_text_size));
            titleName.setTextColor(title_text_color);
            ll_root.setBackgroundColor(title_color);
            if (left_isvisalbe) {
                leftIcon.setVisibility(View.VISIBLE);
                leftIcon.setImageResource(title_left_icon);
            } else {
                leftIcon.setVisibility(View.GONE);
                btnLeft.setEnabled(false);
            }
            if (right_isvisalbe) {
                rightIcon.setImageResource(title_right_icon);
                rightIcon.setVisibility(View.VISIBLE);
            } else {
                rightIcon.setVisibility(View.GONE);
                btnRight.setEnabled(false);
            }
            LinearLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) title_high);
            ll_root.setLayoutParams(params);


        } finally {
            typedArray.recycle();
        }

    }

    public void setLeftClickListener(OnClickListener listener) {
        btnLeft.setOnClickListener(listener);
    }

    public void setRightClickListener(OnClickListener listener) {
        btnRight.setOnClickListener(listener);
    }

    public int getTitle_color() {
        return title_color;
    }

    public void setTitle_color(int title_color) {
        this.title_color = title_color;
        ll_root.setBackgroundColor(title_color);
    }

    public float getTitle_text_size() {
        return title_text_size;
    }

    public void setTitle_text_size(float title_text_size) {
        this.title_text_size = title_text_size;
        titleName.setTextSize(title_text_size);
    }

    public int getTitle_text_color() {
        return title_text_color;
    }

    public void setTitle_text_color(int title_text_color) {
        this.title_text_color = title_text_color;
        titleName.setText(title_text_color);
    }

    public String getTitle_text() {
        return title_text;
    }

    public void setTitleName(String title_text) {
        this.title_text = title_text;
        titleName.setText(title_text);
    }

    public int getTitle_left_icon() {
        return title_left_icon;
    }

    public void setTitle_left_icon(int title_left_icon) {
        this.title_left_icon = title_left_icon;
        leftIcon.setImageResource(title_left_icon);
    }

    public int getTitle_right_icon() {
        return title_right_icon;
    }

    public void setTitle_right_icon(int title_right_icon) {
        this.title_right_icon = title_right_icon;
        rightIcon.setImageResource(title_right_icon);
    }

    public float getTitle_high() {
        return title_high;
    }

    public void setTitle_high(float title_high) {
        this.title_high = title_high;
        LinearLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) title_high);
        ll_root.setLayoutParams(params);
    }

    private void initView() {
        titleName = (TextView) findViewById(R.id.title_name);
        btnLeft = (LinearLayout) findViewById(R.id.btn_left);
        btnRight = (LinearLayout) findViewById(R.id.btn_right);
        leftIcon = (ImageView) findViewById(R.id.left_icon);
        rightIcon = (ImageView) findViewById(R.id.right_icon);
        ll_root = (RelativeLayout) findViewById(R.id.ll_root);
    }
    protected int dp2px(float dp) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }

}
  • 接下了就是怎么使用了,使用的话真的很简单。根据自己的需求可以任意设定即可。需要在根布局中引入匿名约束即这一行代码xmlns:app=”http://schemas.android.com/apk/res-auto”。
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
<com.zh.connent.widget.TitleView
        android:id="@+id/tlv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:left_isVisable="false"
        app:right_isVisable="true"
        app:title_right_icon="@mipmap/discovery_right_icon"
        app:title_text="标题栏"
        />

好了,就是这么简单,直接拿来用就好,有什么问题可以给我留言。

Android 通用标题栏 简单封装实现 Android 通用标题栏 简单封装实现 http://blog.youkuaiyun.com/RichieZhu/article/details/50935918 立即下载

相关推荐

Android自定义TitleView标题开发实例

主要介绍了Android自定义TitleView标题开发实例的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下

Android 自定义View (一)

那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!北京 Android 工程师「工资收入水平 」今天重点内容是怎么去学,怎么提高自己的技术。1.合理安排时间2.找对好的系统的学习资料3.有老师带,可以随时解决问题。

m0_75012072的博客 950

企业碳排放计算方法与实践:从年度总量到月度分配的完整流程

本文系统介绍了企业碳排放计算的全流程方法,包括数据预处理、能源活动与产品生产碳排放计算、年度汇总及月度分配优化。通过ARIMA模型预测补充缺失数据,采用二次规划算法实现基于用电量模式的月度碳排放分配,确保计算结果的准确性与合理性。该方法为企业碳排放管理提供了科学工具,有助于精准监控排放、制定减排策略并满足合规要求。实施中需注重数据质量控制和排放因子选择,并根据企业特点调整参数。该流程适用于制造业企业,为实现碳中和目标提供可靠的数据基础和管理支持。

applehunqiu的博客 1573

自定义控件TitleView

<?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="wrap_content" andr

zhu6201976的博客 7万+

自然二进制数与格雷码的相互转换

自然二进制数与格雷码两者优势: 自然二进制数的编码方式简单明了,容易理解,在加减运算中能够直接进行,同时十分方便进行一些位运算操作(如移位、取反等)。 格雷码计数时只有一位变化,可有效减少计数器状态的冗余转换,同时在传输数据时能够减小传输错误的概率,此外带权重编码处理更加方便。 在一定程度上自然二进制数与格雷码优缺点基本相反,综上所述,自然二进制数和格雷码各有优劣之处,需要根据具体应用场景选择合适的编码方式。简单来说,在计数器和编码器中,倾向于使用格雷码;而在进行加减运算时,则倾向于使用自然二进制数。

Loudrs的博客 7494

关于带布局的自定义View(自定义TitleView)

Android实现自定义TitleView

u013728021的博客 1084

Paddle账户与支付宝功能快速开通指南:全球化支付解决方案

本文为开发者提供了Paddle账户与支付宝功能集成的详细开通与配置指南。通过Paddle这一全球化支付与销售平台,开发者可一站式管理全球支付与税务合规,而集成支付宝则能无缝覆盖中国用户,实现“一个平台,覆盖全球主流支付方式”,有效提升支付转化率与收款效率。

qq_27496129的博客 1121

titleView发生偏移、titleView与masonry、titleView的设置、titleView的使用

navigationItem的titleView属性的设置本身是很简单的,容易出问题的原因是自动化布局与frame混用造成的。 本文一步一步的讲解,力求找到问题的起源。如果你也在这块同样遇到问题,不妨耐下心来,一起看看怎么回事。 titleView这个属性默认值是nil。也就是说,它是不存在的。如果开发者使用[self.navigationItem.titleView addsubV...

CCCCCC1990的博客 884

提升YOLOv8检测精度的边界框损失函数Focaler-IoU与InnerFocalerIoU的应用与效果

YOLOv8是一种常用的实时目标检测模型,基于CNN(卷积神经网络)结构并结合了一些改进技术以提高检测精度和速度。YOLOv8的核心在于边界框的预测和分类,而准确的边界框预测是提高模型整体性能的关键因素之一。在传统的IoU损失基础上,Focaler-IoU和InnerFocalerIoU进一步聚焦于边界框的边缘区域,通过调整损失权重,更好地关注难以检测的边界框,提高模型的鲁棒性和准确性。# 计算IoU# 计算Focaler-IoU损失在这里,我们定义了。

博客 1343

【OpenClaw企业级智能体实战】第11篇:制造业设备预测性维护实战——OpenClaw+DeepSeek+Prometheus从零搭建(附完整代码)

本文聚焦制造业设备预测性维护的核心痛点,基于OpenClaw v2026.2.1、DeepSeek智能诊断、Prometheus监控等工具,拆解“设备状态监控→智能故障诊断→预测性维护”三大核心场景。从技术原理、算法构建、实操流程到完整代码实现,提供“数据采集→模型训练→智能调度→自动处置”的全链路方案。方案遵循工业安全规范,采用“只读优先、权限最小化”原则,适配中小制造企业落地需求。通过虚拟案例验证,可使设备非计划停机时间下降65%、平均修复时间缩短47%,既适合新手快速入门,也为进阶读者提供架构优化思路

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 607

iOS 导航栏TitleView居中的问题

最近在开发中遇到了一个问题,我自定义了一个titleVIew放在navigationBar上面,在iPhone6 和6P上面显示 是 居中的,但是在 5s 和4s 上面显示的时候明显的偏向右边,因为我的titleView 上面有一个lab labText 长度会变化,所以导致我的titleView 显示出现了居中问题。 经过查阅多方资料,我了解到,titleVIew 默认情况下 是居中显示的,出

wbxiaowangzi的博客 4196

AD9613操作控制

输出250M时钟给AD9613,过FPGA ILA逻辑分析仪将AD9613采集的两个通道ADC数据250M数据显示出来。其中AD9613输出的是LVDS数据,通过select IO核转为并行数据。 一,搜索IP核:selectIO interface wizad ,并双击配置 配置为input,DDR模式,数据位宽为12bit,IO类型为差分,这里配置的是12对数据差分对。然后配置外部差分时钟。 将tap setting 设置为13,将时钟的边沿对准数据的中间,以免数据出错 二,

wangjie36的博客 4050

Android用注解打造一个简易的TitleView

最近手上在同时做两个项目,有点疲于奔命,博客都无暇顾及;但是也得出一个心得:做一个项目,首先要审视UI给你的图和后台给你的需求,找到复用之处,这是快速开发的第一步。所以TitleView能不封装吗?我的A项目的title(仿微信的title)B项目的title所以只需要简单封装下返回的按键就可以了至于title name,可以采用注解,免去几行代码,进行优雅的声明,如下所示:全部代码javapub...

qq_36523667的博客 711

Unity零基础到入门 ☀️| 【UI系统学习】轻松学会 Unity 的 UGUI基础控件的使用(包括一个简易血条、蓝条设计)

Unity,UGUI。本篇博客来挑几种Unity中最常用的UI控件如何使用和使用技巧,包括一个简易血条蓝条的小实例

努力前行,总会成为自己心中的那道光 2万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

AXPhotoViewer 完整教程:从零打造你的第一个 iOS 图片浏览器

如果你想为自己的 iOS App 快速加入一个体验流畅、开箱即用的图片浏览器,AXPhotoViewer 绝对是值得优先考虑的开源方案。这款专为 iOS 与 tvOS 打造的图片浏览器组件,能轻松展示几十上百张照片与 GIF 动图,支持上下文转场动画、下拉手势关闭,还能与主流异步图片加载库无缝对接。本教程将带你从零上手,用最短时间打造出属于自己的第一个 iOS 图片浏览器。 ## AXPhoto

gitblog_00008的博客 360

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

自定义带返回按钮的标题

1,项目中基本每个页面都要用到返回按钮以及标题,每次使用每次写就变的很麻烦,也没有必要,所以今天要自定义一个TitleView方便使用。首先,要写个布局文件:里面放一个返回按钮以及一个标题&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/ap...

再也不做的事 724

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

探索 DNSPageView:打造极致的页面切换体验

在移动应用开发中,页面切换是一个常见且重要的功能。无论是新闻应用、电商平台还是社交媒体,流畅且美观的页面切换体验都能显著提升用户满意度。今天,我们将深入介绍一个强大的开源项目——DNSPageView,它以其简洁的API、灵活的布局和丰富的样式选项,成为了Swift开发者的不二之选。 ## 项目介绍 DNSPageView 是一个纯 Swift 编写的轻量级、高度灵活且易于使用的 `PageV

gitblog_01032的博客 525

推荐项目:UINavigationItem+Margin - 打造个性化的iOS导航栏

推荐项目:UINavigationItem+Margin - 打造个性化的iOS导航栏 UINavigationItem-MarginMargins for UINavigationItem项目地址:https://gitcode.com/gh_mirrors/ui/UINavigationItem-Margin 在构建iOS应用时,界面的微小调整往往能够带来用户体验上的巨大飞跃。今天,我们向您...

gitblog_00092的博客 433

终极PagingKit使用教程:打造完全自定义的iOS分页菜单界面

PagingKit是一款功能强大的iOS开源组件库,专门用于创建高度可定制的分页菜单界面。与其他iOS分页库相比,PagingKit提供了无与伦比的布局灵活性和设计自由度,让开发者能够轻松构建符合任何设计规范的分页导航系统。 ## 🎯 PagingKit的核心价值与独特优势 PagingKit的核心设计理念是将行为控制与视觉表现完全分离,这种架构为开发者带来了三大核心优势: **🚀 极致

gitblog_00377的博客 468

PagingKit专业指南:打造高度自定义的iOS分页菜单界面

PagingKit是一款功能强大且高度可定制的iOS分页菜单组件库,为开发者提供了比传统UIPageViewController更灵活的布局和设计能力。无论您是开发简单的标签页导航还是复杂的分页控制器,PagingKit都能帮助您快速实现专业级的UI效果,同时保持代码的简洁性和可维护性。 ## 🔍 PagingKit核心优势与差异化特点 PagingKit的设计理念基于**组合优于继承**的

gitblog_01082的博客 324

Square Cycler与原生RecyclerView对比:开发效率提升300%的终极方案

Square Cycler是一个为Android开发者打造的声明式RecyclerView API,它通过简洁的配置方式让开发者轻松实现复杂列表功能,显著提升开发效率。本文将深入对比Square Cycler与原生RecyclerView的核心差异,揭示如何通过Square Cycler实现开发效率提升300%的秘诀。 ## 🚀 核心差异:声明式 vs 命令式 ### 原生RecyclerV

gitblog_00674的博客 958

从入门到精通:YPNavigationBarTransition配置与最佳实践指南

想要为你的iOS应用打造如微信般流畅自然的导航栏切换效果吗?YPNavigationBarTransition正是你需要的解决方案!这个功能完整的UINavigationBar框架能让你的应用导航栏过渡更加自然流畅,无需调用复杂的UINavigationBar API,只需为视图控制器实现简单的协议即可。 ## 🚀 为什么选择YPNavigationBarTransition? 在iOS开发

gitblog_00178的博客 1059

YPNavigationBarTransition进阶:自定义导航栏背景图片与颜色全攻略

想要让你的iOS应用拥有像微信那样流畅自然的导航栏切换效果吗?YPNavigationBarTransition是一个功能完整的UINavigationBar框架,它能让你轻松实现各种导航栏过渡动画,无需直接调用复杂的UINavigationBar API。本文将为你详细介绍如何利用这个强大的框架自定义导航栏背景图片和颜色,打造独特的应用界面体验。 ## 🎨 YPNavigationBarTr

gitblog_01019的博客 604

Ceph Peering 状态机可视化:使用 gen_state_diagram.py 从 OSD 源码自动生成状态图

本指南围绕 Ceph 仓库中的 [doc/scripts/README.md](https://link.gitcode.com/i/545d3c5a188b42cfc6045c87aa299c53) 展开,完整讲解如何使用 `gen_state_diagram.py` 脚本,直接从 OSD 核心的 Peering 状态机源码(`src/osd/PeeringState.h` / `src/osd

gitblog_00008的博客 787

ai-app-playbook 支付实现指南:Superwall + Stripe Webhook,一张 entitlements 表打通三端 Pro 权限

ai-app-playbook 是一份教你用 AI 编程 Agent 构建并变现 App 的实战手册,支付是新手最容易卡住的一环:iOS、Android、Web 三端各走不同支付渠道,权限却要对齐。本文方案用 **Superwall** 承接移动端、**Stripe** 承接 Web 端,靠 Stripe Webhook 与 Superwall 回调把购买结果统一写进同一张 `entitlemen

gitblog_00987的博客 438
上一篇: 更好用的DialogFragment
下一篇: 爱不释手的ConstraintLayout布局
Code_legend
博客等级 码龄10年 33粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值