FinClip为企业提供小程序生态圈技术产品,开发者可在FinClip小程序开发帮助中心找到相关FinClip小程序指引

# 设置小程序更多菜单

# 1. 效果展示

点击右上角胶囊中的“...”即可唤起如下更多菜单页面

4-1-1.png

# 2. 屏蔽更多菜单中的“转发”按钮

# 2.1 覆盖范围

该设置由App实现,一经设置、App内的全部小程序均将按照本效果实现

# 2.2 iOS 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FATUIConfig *uiConfig = [[FATUIConfig alloc] init];
//屏蔽更多菜单中的“转发”按钮
uiConfig.hideForwardMenu = YES;

# 3. 屏蔽更多菜单中的“设置”按钮

# 3.1 覆盖范围

该设置由App实现,一经设置、App内的全部小程序均将按照本效果实现

# 3.2 iOS 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FATUIConfig *uiConfig = [[FATUIConfig alloc] init];
//屏蔽更多菜单中的“设置”按钮
uiConfig.hideSettingMenu = YES;

# 3.3 Android 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

// UI配置
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// 是否隐藏"更多"菜单中的"设置"按钮
uiConfig.setHideSettingMenu(true);

# 4. 屏蔽更多菜单中的“返回首页”按钮

# 4.1 覆盖范围

该设置由App实现,一经设置、App内的全部小程序均将按照本效果实现

# 4.2 iOS 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FATUIConfig *uiConfig = [[FATUIConfig alloc] init];
//屏蔽更多菜单中的“返回首页”按钮
uiConfig.hideBackToHome = YES;

# 4.3 Android 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// 是否隐藏"更多"菜单中的"返回首页"菜单入口
uiConfig.setHideBackHome(true);

注:

更多菜单中的“返回首页”按钮从2.36.1版本之后已被废弃,该配置项变更为控制导航栏上的“返回首页”按钮。

# 5. 屏蔽更多菜单中的“反馈与投诉”按钮

# 5.1 覆盖范围

该设置由App实现,一经设置、App内的全部小程序均将按照本效果实现

# 5.2 iOS 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FATUIConfig *uiConfig = [[FATUIConfig alloc] init];
//屏蔽更多菜单中的“反馈与投诉”按钮
uiConfig.hideFeedbackMenu = YES;

# 5.3 Android 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// 是否隐藏更多菜单中的"反馈与投诉"
uiConfig.setHideFeedbackAndComplaints(true);

# 6.屏蔽更多菜单中的“重新进入”按钮

# 6.1 覆盖范围

该设置由App实现,一经设置、App内的全部小程序均将按照本效果实现

# 6.2 iOS 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FATUIConfig *uiConfig = [[FATUIConfig alloc] init];
//屏蔽更多菜单中的“重新进入”按钮
uiConfig.hideRefreshMenu = YES;

# 6.3 Android 设置方法

初始化SDK时,通过UI配置项进行配置,如下:

FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// 是否隐藏更多菜单中的"反馈与投诉"
uiConfig.setHideRefreshMenu(true);

# 7. 自行实现更多面板

如果不想使用SDK提供的更多面板,想要自定义实现一个更多面板,可以按照以下方式实现。

# 7.1 覆盖范围

该设置由App实现,可以针对不同的小程序id实现不同的更多面板效果。更多面板完全由App设计实现,里面的视图样式和展示的菜单项都可以自主控制。

# 7.2 iOS设置方法

实现FATAppletDelegate中的appletInfo:didClickMoreBtnAtPath:即可。

首先,自定义一个FATClientHelper类,实现FATAppletDelegate协议。

#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>

@interface FATClientHelper : NSObject<FATAppletDelegate>

+ (instancetype)shareInstance;

@end

然后,在SDK初始化成功后后,设置SDK的代理为 FATClientHelper 对象。

示例代码

[[FATClient sharedClient] initWithConfig:config error:nil];
[FATClient sharedClient].delegate = [FATClientHelper shareInstance];
- (BOOL)appletInfo:(FATAppletInfo *)appletInfo didClickMoreBtnAtPath:(NSString *)path
{
    // 如果您需要自定义更多面板,则在这里写入展示更多面板的逻辑,并返回YES。
    // 如果您不需要自定义更多面板,则可以不写该方法或者返回NO。
    return NO;
}

# 7.3 Android 设置方法

自定义更多面板是通过IAppletProcessHandler来实现的,IAppletProcessHandler会把触发小程序"..."点击事件的onNavigationBarMoreButtonClicked回调给宿主,由宿主实现更多面板的效果。

/**
 * 小程序抽象业务回调接口,SDK将这些抽象的业务通过接口的形式暴露给外部,由外部具体实现
 * (小程序进程)
 */
interface IAppletProcessHandler {

    /**
     * 小程序导航栏中的"更多"按钮被点击
     *
     * @param appId 小程序ID
     * @return 返回true表示自行处理按钮点击事件,不需要执行默认操作(弹出菜单)。返回false表示需要执行默认操作
     */
    fun onNavigationBarMoreButtonClicked(context: Context, appId: String): Boolean
}

onNavigationBarMoreButtonClicked方法实现示例如下:

public class AppletProcessHandler implements IAppletProcessHandler {

    @NonNull
    private Context mContext;

    private AppletProcessHandler() {
    }

    public AppletProcessHandler(@NonNull Context context) {
        this.mContext = context;
    }

    @Nullable
    @Override
    fun onNavigationBarMoreButtonClicked(context: Context, appId: String): Boolean {
        // 如果您需要自定义更多面板,则在这里写入展示更多面板的逻辑,并返回true。
        // 如果您不需要自定义更多面板,则可以返回false。
        return false
    }
}

# 8. 自行注入更多面板里的菜单项

当前SDK支持往更多面板里添加自定义的菜单项,而菜单项按类型可分为common 和 onMiniProgram类型。

  • common: 该类型无需小程序添加额外处理
  • onMiniProgram: 该类型菜单在点击时,会向小程序获取数据用以提供给 App 的业务处理

注意

  1. 自定义的菜单项可由管理后台配置是否显示,管理后台配置的菜单ID要与自定义的菜单ID对应。若管理后台不配置,则不会影响App端注入的菜单。
  2. onMiniProgram类型的菜单,如果要显示必须在当前页面实现on{MenuId}ButtonHandler(id 为首字母大写),例如菜单ID为ShareDingDing,则要实现的方法名onShareDingDingButtonHandler。
  3. 最终更多面板中显示的菜单项,取自管理后台返回的菜单项、App注入的菜单项、小程序当前页面实现的菜单项的交集。

举个例子: 若小程序当前页面实现的菜单项事件集合为A;
App注入的菜单项集合为B,包含common类型菜单的集合B1和onMiniProgram类型菜单的集合B2;
管理后台配置的菜单集合为C;

最终展示的自定义菜单集合结果,分两种情况:

1)如果C为空(安卓端为null,iOS端为nil),则:
A和B2取交集得到D;
D和B1取并集得到E;
最终结果为E。

2)如果C不为空(安卓端不为null,iOS端不为nil),则:
A和B2取交集得到D;
D和B1取并集得到E;
E和C取交集得到F;
最终结果为F。

注意

  1. 如果C为[],则表示不展示所有自定义菜单。
  2. 小程序侧要做的工作,参考小程序-API-自定义菜单
  3. 为什么取交集?由于自定义菜单的行为需要App实现,如果仅仅由后台配置,那么会导致展示了菜单,而点击没有响应的情况。

# 8.1 覆盖范围

该设置由App实现,可以针对不同的小程序id,在SDK的更多面板中注入不同的自定义菜单项。

# 8.2 iOS 设置方法

实现FATAppletDelegate中的customMenusInApplet:atPath:customMenu:inApplet:didClickAtPath:即可。

首先,自定义一个FATClientHelper类,实现FATAppletDelegate协议。

#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>

@interface FATClientHelper : NSObject<FATAppletDelegate>

+ (instancetype)shareInstance;

@end

然后,在SDK初始化成功后后,设置SDK的代理为 FATClientHelper 对象。

示例代码

[[FATClient sharedClient] initWithConfig:config error:nil];
[FATClient sharedClient].delegate = [FATClientHelper shareInstance];

再然后,实现自定义菜单Model,需要实现FATAppletMenuProtocol协议。

@interface FATCustomMenuModel : NSObject<FATAppletMenuProtocol>

@end


// 返回要注入的菜单对象,菜单对象必须实现 FATAppletMenuProtocol 协议
// 菜单对象分为两种类型(默认为Common类型):
// 1.Common类型:配置则显示
// 2.OnMiniProgram类型:需要后台配置+小程序配置,取相同menuId的集合显示
// PS: 这里兼容旧版本,若后台未升级版本,或后台升级版本后未配置,则仅需要适配菜单对象的menuId为NSString类型
- (NSArray<id<FATAppletMenuProtocol>> *)customMenusInApplet:(FATAppletInfo *)appletInfo atPath:(NSString *)path
{
    FATCustomMenuModel *favModel1 = [[FATCustomMenuModel alloc] init];
    favModel1.menuId = @"WXShareAPPFriends";
    favModel1.menuTitle = @"微信好友";
    favModel1.menuIconImage = [UIImage imageNamed:@"mini_menu_chat"];
    favModel1.menuType = FATAppletMenuStyleOnMiniProgram;//为需要和小程序有交互的菜单类型,例如分享小程序按钮,点击按钮分享小程序时,可能需要获取到小程序的一些数据

    // 默认为普通菜单类型,不需要和小程序有交互
    FATCustomMenuModel *favModel2 = [[FATCustomMenuModel alloc] init];
    favModel2.menuId = @"1002";
    favModel2.menuTitle = @"微信朋友圈";
    favModel2.menuIconImage = [UIImage imageNamed:@"mini_menu_timeline"];
    
    return @[favModel1, favModel2];
}

// 点击自定义菜单时的事件(旧版,后台未升级或升级后未配置菜单时使用)
- (void)customMenu:(id<FATAppletMenuProtocol>)customMenu inApplet:(FATAppletInfo *)appletInfo didClickAtPath:(NSString *)path
{
    NSLog(@"点击了%@",customMenu.menuTitle);
    NSLog(@"path = %@",path);
}

// 点击自定义菜单时的事件(新版,后台与小程序配置时使用)
- (void)clickCustomItemMenuWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode, NSDictionary *))completion 
{
    /**
    contentInfo 中包含
    {
         @"title": @"标题",
         @"description": @"描述",
         @"imageUrl": @"图片路径",
         @"path": @"点击时的小程序页面路径"",
         @"menuId": @"点击的菜单按钮标识",
         @"params": self.params     // 原始参数数据,由小程序提供
    }
    */
    // 小程序回调调用,通知小程序点击事件处理情况
    completion(FATExtensionCodeSuccess, contentInfo);
}

# 8.3 Android 设置方法

“更多”菜单中菜单项的注入通过IAppletHandler来实现的,IAppletHandler会把获取注入菜单项的接口方法getRegisteredMoreMenuItems和点击注入菜单项的接口方法onRegisteredMoreMenuItemClicked回调给宿主应用,由宿主应用实现具体的业务逻辑。

getRegisteredMoreMenuItemsonRegisteredMoreMenuItemClicked如下:

/**
 * 获取注册的"更多"菜单项
 *
 * @param appId 小程序ID
 * @return 注册的"更多"菜单项
 */
fun getRegisteredMoreMenuItems(appId: String): List<MoreMenuItem>?

/**
 * 注册的"更多"菜单项被点击
 *
 * @param appId 小程序ID
 * @param path 小程序页面路径
 * @param menuItemId 被点击的菜单条目的ID
 * @param appInfo 小程序信息,是一串json,包含了小程序id、小程序名称、小程序图标、用户id、转发的数据内容等信息。
 * [appInfo]的内容格式如下:
 * {
 *      "appTitle": " FinClip 小程序",
 *      "appAvatar": "https:\/\/www.finogeeks.club\/statics\/images\/swan_mini\/swan_logo.png",
 *      "appId": "5df36b3f687c5c00013e9fd1",
 *      "appType": "trial",
 *      "userId": "finogeeks",
 *      "cryptInfo": "SFODj9IW1ENO8OA0El8P79aMuxB1DJvfKenZd7hrnemVCNcJ+Uj9PzkRkf/Pu5nMz0cGjj0Ne4fcchBRCmJO+As0XFqMrOclsqrXaogsaUPq2jJKCCao03vI8rkHilrWxSDdzopz1ifJCgFC9d6v29m9jU29wTxlHsQUtKsk/wz0BROa+aDGWh0rKvUEPgo8mB+40/zZFNsRZ0PjsQsi7GdLg8p4igKyRYtRgOxUq37wgDU4Ymn/yeXvOv7KrzUT",
 *      "params": {
 *           "title": "apt-test-tweet-接口测试发布的动态!@#¥%……&*(",
 *           "desc": "您身边的服务专家",
 *           "imageUrl": "finfile:\/\/tmp_fc15edd8-2ff6-4c54-9ee9-fe5ee034033d1576550313667.png",
 *           "path": "pages\/tweet\/tweet-detail.html?fcid=%40staff_staff1%3A000000.finogeeks.com&timelineId=db0c2098-031e-41c4-b9c6-87a5bbcf681d&shareId=3dfa2f78-19fc-42fc-b3a9-4779a6dac654",
 *           "appInfo": {
 *               "weixin": {
 *                   "path": "\/studio\/pages\/tweet\/tweet-detail",
 *                   "query": {
 *                       "fcid": "@staff_staff1:000000.finogeeks.com",
 *                       "timelineId": "db0c2098-031e-41c4-b9c6-87a5bbcf681d"
 *                    }
 *               }
 *           }
 *       }
 * }
 * [appInfo]中各字段的说明:
 * appId 小程序ID
 * appTitle 小程序名称
 * appAvatar 小程序头像
 * appType 小程序类型,其中trial表示体验版,temporary表示临时版,review表示审核版,release表示线上版,development表示开发版
 * userId 用户ID
 * cryptInfo 小程序加密信息
 * params 附带的其它参数,由小程序自己透传
 *
 * @param bitmap 小程序封面图片。如果[appInfo].params.imageUrl字段为http、https的链接地址,那么小程序封面图片
 * 就取[appInfo].params.imageUrl对应的图片,否则小程序的封面图片取[bitmap]。
 * @param callback 结果回调。
 */
fun onRegisteredMoreMenuItemClicked(appId: String, path: String, menuItemId: String, appInfo: String?, bitmap: Bitmap?, callback: IAppletCallback)

IAppletHandler实例需要通过调用IAppletApiManagersetAppletHandler(appletHandler: IAppletHandler)方法传入。

getRegisteredMoreMenuItems方法和onRegisteredMoreMenuItemClicked方法实现示例如下:

/**
 * {@link IAppletHandler}实现类,用于实现一些业务场景,例如注册"更多"菜单项,转发小程序等。
 */
public class AppletHandler implements IAppletHandler {

    @NonNull
    private Context mContext;

    private AppletHandler() {
    }

    public AppletHandler(@NonNull Context context) {
        this.mContext = context;
    }

    @Nullable
    @Override
    public List<MoreMenuItem> getRegisteredMoreMenuItems(@NotNull String appId) {
        List<MoreMenuItem> items = new ArrayList<>();
        MoreMenuItem item0 = new MoreMenuItem("WXShareAPPFriends", "微信好朋友", MoreMenuType.ON_MINI_PROGRAM);
        items.add(item0);
        MoreMenuItem item1 = new MoreMenuItem("WXShareAPPMoments", "微信朋友圈", MoreMenuType.ON_MINI_PROGRAM, true);
        items.add(item1);
        MoreMenuItem item2 = new MoreMenuItem("ShareSinaWeibo", "新浪微博", MoreMenuType.ON_MINI_PROGRAM);
        items.add(item2);
        MoreMenuItem item3 = new MoreMenuItem("ShareQQFirends", "QQ", MoreMenuType.ON_MINI_PROGRAM);
        items.add(item3);
        MoreMenuItem item4 = new MoreMenuItem("ShareDingDing", "Dingding", MoreMenuType.ON_MINI_PROGRAM);
        items.add(item4);
        MoreMenuItem item5 = new MoreMenuItem("ShareLinks", "标题以后端配置为准", MoreMenuType.ON_MINI_PROGRAM);
        items.add(item5);
        MoreMenuItem item6 = new MoreMenuItem("SharePicture", "SharePicture", MoreMenuType.ON_MINI_PROGRAM);
        items.add(item6);
        MoreMenuItem item7 = new MoreMenuItem("Restart", "Restart", MoreMenuType.COMMON);
        items.add(item7);
        MoreMenuItem item8 = new MoreMenuItem("Desktop", "Desktop", MoreMenuType.COMMON);
        items.add(item8);
        return items;
    }

    @Override
    public void onRegisteredMoreMenuItemClicked(@NotNull String appId, @NotNull String path, @NotNull String menuItemId, @Nullable String appInfo, @Nullable Bitmap bitmap, @NotNull IAppletCallback callback) {
        Toast.makeText(mContext, "小程序" + appId + "的" + path + "页面的菜单" + menuItemId + "被点击了,appInfo : " + appInfo + " bitmap : " + bitmap, Toast.LENGTH_SHORT).show();
        callback.onSuccess(null);
    }
}

MoreMenuItem为菜单条目数据类,如下:

/**
 * 更多菜单条目
 *
 * @param id 菜单条目ID
 * @param title 菜单菜单条目标题
 * @param image 菜单条目图标地址
 * @param icon 菜单条目图标对应的资源ID
 * @param type 菜单条目类型
 * @param isEnable 菜单条目是否可用
 */
data class MoreMenuItem(val id: String,
                        val title: String,
                        val image: String,
                        @DrawableRes val icon: Int,
                        val type: MoreMenuType = MoreMenuType.COMMON,
                        val isEnable: Boolean = true) {

    /**
     * 构造方法
     * @param id 菜单条目ID
     * @param title 菜单菜单条目标题
     * @param type 菜单条目类型[MoreMenuType.COMMON]或[MoreMenuType.ON_MINI_PROGRAM]
     */
    constructor(id: String, title: String, type: MoreMenuType) : this(id, title, "", -1, type, true)
}

MoreMenuType是一个枚举类,如下:

/**
 * 更多菜单类型
 * [COMMON]为普通菜单类型,不需要和小程序有交互
 * [ON_MINI_PROGRAM]为需要和小程序有交互的菜单类型,例如分享小程序按钮,点击按钮分享小程序时,可能需要获取到小程序的一些数据
 */
enum class MoreMenuType {
    COMMON, ON_MINI_PROGRAM
}
© 2022 FinClip with ❤

👋🏻 嘿,你好!

「FinClip」是一套基于云原生框架设计的小程序容器。能够让任何移动应用在集成小程序SDK之后,获得可用、安全的小程序运行能力。

>> 点我免费注册体验

查看产品文档
了解与 FinClip 相关的一切信息

产品博客 👈  了解产品更新与核心功能介绍
资源下载 👈  获取小程序 SDK 与开发工具
文档中心 👈  查询 FinClip 小程序开发指南与答疑

商务咨询热线
预约 FinClip 产品介绍,咨询商务报价或私有化部署事宜

0755-86967467

获取产品帮助
联系 FinClip 技术顾问,获取产品资料或加入开发者社群

联系线上
人工客服

或 👉  点击这里,提交咨询工单