手游海外SDK实战——Android客户端之UI篇
一、前言
随着国内手游版号申请难度的增加,以及防沉迷等一系列政策的影响,很多国内开发者纷纷开始寻求海外发行之路。那么手游出海首要的是需要一套适合海外发行和运营的手游SDK联运系统。
本系列我们就来开发一套这样的SDK,我们暂且称这套SDK为UGSDK。该SDK已经开发完成,如果有兴趣或者想体验完整功能的同学,可以加我们的海外技术交流QQ群:1055996444。
整个UGSDK项目,暂时可以分为三大部分——Android客户端SDK部分、iOS客户端SDK部分以及服务端部分(目前不考虑H5游戏部分)。
本篇主要介绍UGSDK项目中Android客户端部分中的UI和流程控制设计。
二、UI设计
1、设计原则
1 2 3 4 5 6 |
1、每个界面采用单独一个fragment,fragment能重复利用尽可能重复利用。 2、单个fragment中,只能放一个UI界面,不可以将多个UI界面放到一个fragment中。 3、fragment中禁止处理流程跳转,也就是不会直接在一个fragment中push进另一个fragment。 4、流程的控制(fragment的跳转),统一在fragment归属的activity中处理。 5、fragment和activity之间的流程交互,采用回调的方式处理。 |
2、设计样例:
我们来看下游客升级提示界面的fragment, 演示如何设计单个UI界面的fragment以及处理流程中需要被所属Activity托管的部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
public class VisitorFragment extends BaseFragment { private IVisitorFlowCallback flowCallback; public void setFlowCallback(IVisitorFlowCallback callback) { this.flowCallback = callback; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(ResourceUtils.getResourceID(activity, "R.layout.ug_layout_visitor"), container, false); TextView btnSwitch = (TextView) ResourceUtils.getViewByParent(view, "R.id.ug_visitor_switch"); btnSwitch.setClickable(true); TextView btnContinue = (TextView) ResourceUtils.getViewByParent(view, "R.id.ug_visitor_continue"); btnSwitch.setClickable(true); Button btnUpgrade = (Button) ResourceUtils.getViewByParent(view, "R.id.ug_btn_upgrade"); btnUpgrade.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (flowCallback != null) { flowCallback.onVisitorUpgradeAccount(); } } }); btnSwitch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (flowCallback != null) { flowCallback.onVisitorSwitchAccount(); } } }); btnContinue.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (flowCallback != null) { flowCallback.onVisitorContinued(); } } }); return view; } public interface IVisitorFlowCallback { void onVisitorUpgradeAccount(); void onVisitorSwitchAccount(); void onVisitorContinued(); } } |
三、UI流程控制
UI流程的控制,我们采用每个业务流程对应一个单独的activity。 这样我们可以轻松控制流程中不同fragment的跳转以及流程的生命周期,同时也可以最大化fragment的复用。
我们以游客升级这个的流程为例。 该流程总共有三个UI界面,游客升级提示界面-》点击升级,弹出账户升级界面-》点击升级,弹出输入邮箱验证码界面-》点击确定,发送协议给服务端完成账号升级。
在UGSDK中, 我们定义一个VisitorUpgradeActivity来处理这个流程, 我们先来看下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
public class VisitorUpgradeActivity extends BaseFragmentActivity implements VisitorFragment.IVisitorFlowCallback, RegisterFragment.IRegisterFlowCallback, EmailCodeFragment.IEmailCodeFlowCallback { // 游客账号提示界面 private VisitorFragment visitorFragment; // 账号升级界面(重用注册界面) private RegisterFragment upgradeFragment; // 输入邮箱验证码界面 private EmailCodeFragment emailCodeFragment; private String email; private String password; private String code; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); visitorFragment = findOrCreateFragment(VisitorFragment.class); upgradeFragment = findOrCreateFragment(RegisterFragment.class); upgradeFragment.setTitle(ResourceUtils.getString(this, "R.string.ug_visitor_upgrade_title")); upgradeFragment.setButtonText(ResourceUtils.getString(this, "R.string.ug_visitor_upgrade_btn")); upgradeFragment.setBackText(ResourceUtils.getString(this, "R.string.ug_visitor_upgrade_cancel")); emailCodeFragment = findOrCreateFragment(EmailCodeFragment.class); // 首次启动,防止重复fragment堆叠 if (savedInstanceState == null) { push(visitorFragment); } } @Override public void onAttachFragment(Fragment fragment) { if(fragment instanceof VisitorFragment) { ((VisitorFragment)fragment).setFlowCallback(this); } else if(fragment instanceof RegisterFragment) { ((RegisterFragment)fragment).setFlowCallback(this); } else if (fragment instanceof EmailCodeFragment) { ((EmailCodeFragment)fragment).setFlowCallback(this); } } /** * 游客账号提示界面,点击升级账号,跳转到账号升级界面 */ @Override public void onVisitorUpgradeAccount() { push(upgradeFragment); } /** * 游客账号提示界面,点击切换账号,跳转到登录Activity */ @Override public void onVisitorSwitchAccount() { // 这里不直接切到登录界面Activity, 直接触发logout,让游戏返回到游戏登录界面,然后再主动登录。 this.finish(); SDKManager.getInstance().onLogout(); } /** * 游客账号界面,点击继续,直接关闭该Activity */ @Override public void onVisitorContinued() { this.finish(); } /** * 从账号注册界面返回 */ @Override public void onGotoEmailLogin() { fragmentManager.popBackStack(); } /** * 跳转到邮箱验证码输入界面 */ @Override public void onGotoEmailVerify(String email, String password) { this.email = email; this.password = password; push(emailCodeFragment); } /** * 从邮箱验证码返回 */ @Override public void onEmailCodeBack() { fragmentManager.popBackStack(); } /** * 点击邮箱验证码验证, 账号升级成功。继续游戏 */ @Override public void onEmailCodeVerify(String code) { this.code = code; doUpgrade(); } // 发送注册协议 private void doUpgrade() { UGUser user = SDKManager.getInstance().getLoginedUser(); if(user == null) { ResourceUtils.showTip(this, "R.string.ug_upgrade_failed_no_login"); return; } showLoading(); UserApi.upgrade(user, email, password, code, new IApiListener<UGUser>() { @Override public void onSuccess(final UGUser data) { VisitorUpgradeActivity.this.runOnUiThread(new Runnable() { @Override public void run() { hideLoading(); VisitorUpgradeActivity.this.finish(); EmailAccountStore.getInstance().saveEmailAccount(new UGEmailAccount(email, password)); SDKManager.getInstance().onUpgradeSuccess(Constants.LoginType.Email, data); } }); } @Override public void onFailed(final int code, final String msg) { Log.e(Constants.TAG, "doUpgrade failed. code:" + code + ";msg:" + msg); VisitorUpgradeActivity.this.runOnUiThread(new Runnable() { @Override public void run() { hideLoading(); if (code == ApiRequest.R_CODE_FAIL) { ResourceUtils.showTip(VisitorUpgradeActivity.this, msg); } else { ResourceUtils.showTip(VisitorUpgradeActivity.this, "R.string.ug_upgrade_failed"); } } }); } }); } } |
通过上面的代码,我们可以看到, 该流程Activity中, 维护了流程中三个步骤对应的三个fragment:VisitorFragment, RegisterFragment和EmailCodeFragment,并实现了三个Fragment中流程交互对应的Callback。
在onCreate中, 预先初始化了三个fragment,并将第一个步骤游客升级提示fragment给展示了出来。在onAttachFragment中,我们将三个fragment的流程回调监听类都设置为当前activity自身。
下面其他的方法都是对应各个fragment中操作之后对应的流程控制方法了, 在不同的方法中,我们处理流程的跳转或者结束。
最终在最后一步操作,输入邮箱验证码之后,我们像服务端发送请求,完成整个业务流程。
好了,本篇我们介绍了在UGSDK中简化UI和业务流程的控制。感兴趣的同学可以加入我们的技术交流Q裙哦(1055996444)。
本文出自 U8SDK技术博客,转载时请注明出处及相应链接。
本文永久链接: http://www.uustory.com/?p=2408