现在大多数的 PM /交互/ UI 设计师,在设计产品的时候都是以 iOS 为基准 思考产品上的各种功能逻辑、交互状态,而很容易忽略了某些功能在 Android 里并不能「一稿适应两端」,部分产品差异在安卓上是不一样的。
所以本文就讲下 Android 和 iOS 9大产品/交互差异,希望你在日后的产品设计时,可以考虑到更多层面的知识点。
对在于一些虚拟商品的支付上,如 vip 会员、xx币,xx豆。iOS 和 Android 就存在不同的支付规则:Android 基本无限制,无抽成。而 iOS 限制比较多,而且要抽成大约 30% 的手续费。
举个例子:同样充值 30 元,Android 端会得到 300 金币,而在 iOS 中,只有 210 金币。正因这个抽成规则的不同(没办法,这是苹果硬性规定的),才会出现各种平台的虚拟货币,在 Android 和 iOS 中的充值比例是不一样的,如快手:
所以对于虚拟商品在 iOS 端的抽成规则,在产品设计时一定得考虑清楚,因为这关系产品的商业和盈利模式。通常有 2 种解决思路:
A. 让用户承担 30% 的抽成:
同样的价格,iOS 用户得到的商品少些
如同样充值 30 元,Android 端会得到 300 金币,而在 iOS 中,只有 210 金币。像快抖音、陌陌等各种货币充值。
同样的商品,iOS 用户支付更高的费用
如 3 个月的 vip 会员,Android 端定价是 58 元,iOS 端则可以设为 68 元。如优酷、腾讯视频的 vip 会员价格。
B. 公司自己承担 30% 的抽成:
如 iOS 端充值 30 元,公司实收 21 元,但 iOS 用户能得到和 Android 一样的 300 个金币。(理论上是有这个解决思路,但现实中很少有公司去实现,毕竟抽成成本就摆在那里)
另外还需要注意的是:因为抽成规则的不同,对于同一个 ID 的账户余额,在 Android 和 iOS 端中是不能通用的。因此在产品设计时需要将这点告知用户,预防用户犯错、以及恶意刷币。
Android 由于开源的特性,因此对接的都是第三方支付平台,如微信支付、支付宝、银联卡等。 而 iOS 出于系统的封闭性和安全性考虑,只能调用苹果自己的支付系统:登录 Apple ID ,然后用授权的支付方式(支付宝、银联卡)进行付款。
「状态栏」也就是我们手机界面最顶部的电池栏,它除了可以在不同背景里切换颜色外,在交互的触发上,Android 和 iOS 中也各不相同。
iOS :用户在 Y 轴滚动了很长内容时,点击状态栏可以快速回到初始位置。
Android :无论用户滚动了多长内容,都是点击无任何效果。
虽然这一交互差异是 iOS 专有的,但它却启发我们一个新的设计思路:在必要的时候,状态栏可以为产品承载新的交互状态。如网易的 LOFTER( iOS 端),用户离开音乐播放界面时,状态栏就用于显示音乐信息和操作入口,方便用户在浏览其他内容时可以快速关闭音乐,极大提升了用户的操作效率。
这种大多应用于运营的「拉新」场景,为了能让新用户得到好处(红包、优惠券、更好看的内容等)。通常会让新用户下载产品 APP 领取。而由于 Android 与 iOS 的下载方式不同,会带来不同的交互状态和产品逻辑。
Android :可以在当前页面(后台)下载,也可以在应用商店下载;过程中可以显示进度,且允许用户暂停下载;下载完成后调起安装页面,用户可以取消安装,也可以自动安装……正因为 Android 下载软件的各种便捷性,所以才会带来各种交互状态:未下载、下载中、暂停中、已下载但未安装、已安装。这些都是交互设计师需要特别注意的,每个不同的状态背后都会不同的产品逻辑。
iOS :只能跳转到 App Store 里下载,所有下载流程和状态都是在那完成的,可以脱离开活动页面,相比于 Android 的下载方式就简单很多。跳转的方式可以是全屏幕,也可以是半屏。
Android :由于安卓的开源特性,当有新版本时都会提示用户更新,且每个产品内部都带有「版本更新」入口。而更新的方式可分 2 种:
iOS :而 iOS 端出于对用户体验的考虑,是禁止向用户提示版本更新信息的。这也是为什么绝大部分的 iOS 产品,都是没有「版本更新」入口的原因(像 QQ 、支付宝、百度网盘等大厂产品)。
即使有,点击了也直接跳转到 App Store 查看版本情况。且下载渠道都固定在 App Store 里。理所应当的,软件的更新方式也只能在 App Store 里进行,无法做到与 Android 一样后台下载、后台更新。
在手机键盘里输入文字时,iOS 由于系统的限制,对文字的发送指令只能在键盘上来完成,因此 iOS 用户的交互操作都全部集中在键盘右下角。
而 Android 端就灵活很多,不仅可以在键盘上执行发送指令,也可以在输入栏/搜索栏周边新增操作入口。
长按一张图片后,都会弹出一个列表浮层,因为 iOS 手机只有一个「Home 键」 而已,为方便用户退出浮层才增加了「取消」入口。
而 Android 手机本来就有「返回」虚拟键,安卓用户的退出/返回行为都习惯于通过虚拟键触发,所以多做一个「取消」的意义性不大。
iOS 端一直教育着用户使用「左滑」删除列表信息,所有的删除功能都是支持「左滑」来实现的。
而 Android 系统大部分只能通过「长按」来触发编辑状态,其中就包括了删除功能。
不过现在也有极少数的产品,正在逐渐打破这两端间的「删减」界限,比如网易邮箱(Android)就做到了左滑删除信息。
当我们第一次打开产品、允许了获取消息通知的权限后,所有的信息传输都会基于服务器进行推送。而两端在这块的推送机制又有所不同:
iOS :所有新信息都会实时推送到你的手机里,即使你关闭了软件,还是一样会收到提示。就算是你处于断网状态,信息也会先储存于苹果服务器,等你联网时再一次性把收到的信息推送给你。既释放手机内存,又不会让用户遗漏有新消息。
Android :而安卓则不同,你若退出了产品,数据的推送只有等你再次打开产品时,才会通知你有多少新信息。虽然减少了对用户的干扰性,但也增加了服务器数据储存的压力,还容易耽误用户接收新消息。
也就是我们手机的搜狗输入法键盘,在微信聊天内、手机短信里复制了一段内容后,由于 Android 与 iOS 的平台特性差异,会给两端用户带来不同的交互差异。
iOS :复制完文字后,打开输入法键盘会显示来自剪切板的文字内容。用户只需点击,即可将文字复制在搜索栏、输入栏等需要文字填写的操作区域里,无需触发「粘贴」操作。
Android :而有些安卓机(如小米/锤子/乐视等),无论你复制了什么信息(文字、数字、网址等),都很难实现输入法里的「剪切板」功能。用户需要触发「粘贴」功能,才能输入刚刚的复制内容。
而对于特定的信息类型:如网址。用户复制网址往往都带有极强的目标性、搜索性,一些浏览器产品会预判用户这一操作行为,将复制的网址前置展示出来,以抵消 Android 端对于复制文字带来的系统限制。如 QQ 浏览器(安卓端)就有 2 种解法方法:
方法1:利用安卓系统的消息权限,在手机界面的顶部弹出网址栏提示,无论是在微信还是短信中,复制网址后都能快速地触达目标。
方法2:复制网址后打开搜索功能,会将网址自动定位并粘贴到搜索栏中,便于用户查询。
而 UC 和百度也有类似的解决办法:将复制后的广泛信息(文字/数字/网址/邮箱地址等等)嵌入在搜索框下方,用户点击就能搜索。
这也是一种妥当的解决方法,因为用户可复制的信息类型特别广泛、目标不是很清晰。无法准确判断出用户一定会有搜索诉求。所以才将复制后的信息放在搜索框下面,而不是自动粘贴到搜索框中,既考虑了用户目标,又兼顾了操作效率。
以上就是 Android 与 iOS 的差异总结,若有描述得不当请多指教!下面是总结文件。
转载请注明:优设网
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
更多精彩文章:
手机及小程序界面设计之一:让设计更有说服力的20条经典原则:菲茨定律
手机及小程序界面设计之六:让设计更有说服力的20条经典原则:菲茨定律
手机及小程序界面设计之八:如何适配iPhone X?来看滴滴出行的实战案例复盘!
闲着没事儿写了个小 demo ,获取手机上已安装应用信息,系统应用和 非系统应用
MD5 SHA1 SHA256 签名信息 点击签名信息可复制到剪切板,
GitHub:https://github.com/sunan-n/GetAppInfo
如下图:
<span style="white-space:pre;"> </span>主要就是这个方法,传参数进来获取相应的签名类型 信息<br />
public static String getSignaturesInfo(Context context, String packageName, String tpye) {<br />
// //获取包管理器<br />
PackageManager pm = context.getPackageManager();<br />
//返回包括在包中的签名信息<br />
int flags = PackageManager.GET_SIGNATURES;<br />
PackageInfo packageInfo = null;<br />
try {<br />
//获得包的所有内容信息类<br />
packageInfo = pm.getPackageInfo(packageName, flags);<br />
} catch (PackageManager.NameNotFoundException e) {<br />
e.printStackTrace();<br />
}<br />
//签名信息<br />
Signature[] signatures = packageInfo.signatures;<br />
byte[] cert = signatures[0].toByteArray();<br />
//将签名转换为字节数组流<br />
InputStream input = new ByteArrayInputStream(cert);<br />
//证书工厂类,这个类实现了出厂合格证算法的功能<br />
CertificateFactory cf = null;<br />
try {<br />
cf = CertificateFactory.getInstance("X509");<br />
} catch (CertificateException e) {<br />
e.printStackTrace();<br />
}<br />
//X509证书,X.509是一种非常通用的证书格式<br />
X509Certificate c = null;<br />
try {<br />
c = (X509Certificate) cf.generateCertificate(input);<br />
} catch (CertificateException e) {<br />
e.printStackTrace();<br />
}<br />
String hexString = null;<br />
try {<br />
//加密算法的类,这里的参数可以使MD4,MD5等加密算法<br />
// MessageDigest md = MessageDigest.getInstance("SHA1");<br />
MessageDigest md = MessageDigest.getInstance(tpye);<br />
//获得公钥<br />
byte[] publicKey = md.digest(c.getEncoded());<br />
//字节到十六进制的格式转换<br />
hexString = byte2HexFormatted(publicKey);<br />
} catch (NoSuchAlgorithmException e1) {<br />
e1.printStackTrace();<br />
} catch (CertificateEncodingException e) {<br />
e.printStackTrace();<br />
}<br />
return hexString;<br />
}<br />
<br />
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
MVP架构在Android这一块已经盛行依旧,对于一些学习能力比较强的人来说,已经能够运用自如甚至改造优化了,对于吾等菜鸟,却是如此的陌生,今日这篇博客,算是小弟在学习和应用上的一点总结罢了,如有不足,还请各位大神不吝指教。
MVP架构是什么就不多说了,博主主要很大家分享的是,如何设计MVP架构。
先来分析一下MVP如何使用:M-V-P三层之间,P作为中间层,负责M,V之间的数据交互的中介,将数据从M层获取,处理之后提交到V层,换句话说,V需要持有P的实例,P层需要持有V的实例。原理很简单,使用泛型对数据进行封装处理:
2.定义一个P层的接口:
3.封装P基类:绑定解绑V实例
4.M层封装:
之后,将数据提交到activity或者fragment就行了。
收工,MVP基础框架搭建完成了。没错,就是基础框架,但是能不能用呢,让我们拭目以待吧。
然后是Presneter:
最后来完成Activity的逻辑:
1.定义一个V层的空接口,主要是方便封装:
/**
* V层接口
*/ public interface IView { }
/**
* 抽象为接口
*
*/ public interface IPresenter<V extends IView> { /**
* 绑定视图
*
* @param view
*/ void attachView(V view); /**
* 解除绑定(每个V记得使用完之后解绑,主要是用于防止内存泄漏问题)
*/ void dettachView();
}
/**
* 抽象类 统一管理View层绑定和解除绑定
*
* @param <V>
*/ public class BasePresenter<V extends IView, M extends IModel> implements IPresenter<V> { private WeakReference<V> weakView; protected M model;
public V getView() { return proxyView;
} /**
* 用于检查View是否为空对象
*
* @return */ public boolean isAttachView() { return this.weakView != null && this.weakView.get() != null;
} @Override public void attachView(V view) { this.weakView = new WeakReference<V>(view);
} @Override public void dettachView() { if (this.weakView != null) { this.weakView.clear(); this.weakView = null;
}
}
}
/**
* M层
*/ public interface IModel { } /**
* 登录model
* Created by admin on 2018/2/5.
*/ public interface ILoginModel extends IModel { void login();
} /**
* 登录
* Created by admin on 2018/2/5.
*/ public class LoginModel implements ILoginModel { @Override public void login() { // TODO: 2018/2/5 发起登录请求 }
}
最基本的铺垫已经做好了,接下来就该封装View了:
/**
* Created by admin on 2018/2/5.
*/ public abstract class MvpActivity<V extends IView, P extends BasePresenter<V>> extends AppCompatActivity implements IView { private P presenter;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);
...
presenter=getPresenter();
presenter.attachView(this);
} protected P getPresenter() { return presenter;
} protected void setPresenter(P presenter) { this.presenter = presenter;
} protected V getView() { return (V) this;
}
...
@Override protected void onDestroy() {
presenter.dettachView();
... super.onDestroy();
}
}
先来写一个View:
public interface ILoginView extends IView { void onLoginSuccess(); void onFailed();
}
/**
* Created by admin on 2018/2/5.
*/ public class LoginPresenter extends BasePresenter<ILogin, LoginModel> { public LoginPresenter() {
model = new LoginModel();
}
public void login(){
model.login(new LoginCallBack() { @Override public void onSuccess() { if(null!=(ILogin)getView()){
weakView.onLoginSuccess();
}
} @Override public void onFailure() { if(null!=(ILogin)getView()){
weakView.onFailure();
}
}
});
}
}
public class LoginActivity extends MvpActivity<ILoginView, LoginPresenter> implements ILoginView { ...
@Override public LoginPresenter getPresenter() { return new LoginPresenter();
} public void login(View view) {
String name = etUserName.getText().toString();
String pwd = etUserPwd.getText().toString();
getPresenter().login(name, pwd);
}
@Override public void onLoginSuccess() {
}
@Override public void onFailed(){
...
}
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。之前有粉丝留言说希望我们能写一篇关于iOS和Android平台特性对比的文章,笔者曾经为两个平台分别做过差异化的设计,所以今天想借此话题为大家介绍一下iOS和Android两个系统在设计方面的差异之处,让大家能更好的理解其中的异同并运用在自己的设计当中。
作为智能手机的最大的两个阵营,iOS和Android系统差异一向都是大家津津乐道的话题,其中内容通常是围绕“机器性能好不好,打开软件卡不卡”“摄像头的像素高不高,拍出来的自己美不美”“外观是不是有bigger”等话题展开的。
但在一个设计师眼里,这两个系统的差异性之多可远远不止表面上看起来的那么简单粗暴。但在移动端趋势有如春草那样蔓延开来的今天,大多数的公司都选择把iOS的界面直接运用于Android系统。我们自然可以理解这样做是为了节省成本和更快的迭代,但抹杀了系统特性的运用却牺牲了许多Android用户的用户体验。尽管知乎也有类似回答过两个系统交互的不同,今天笔者想更着重介绍一下两者设计语言的异同。
部分原生控件上只存在风格上的差异,对用户无显著影响。
Material Design 不会大兴其道,更不可能逆袭(用 Material Design 设计的 App 在 iOS 上使用),iOS 的实用主义设计会显著影响 Material Design。
桌面常见的交互形式也将更多影响移动端,要支持 iPad Pro 这样的生产级设备,iOS/Android 会为了兼容桌面场景作出优化。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供有效的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
来源:莫贝网
仔细阅读MD的规范,似乎写的很清楚,但是如果和Android4.0规范放在一起,还是会发现很多有出入的地方。不过规范的目的是为了培养并迎合用户使用习惯,减少用户认知负担。文字是死的,人是活的,灵活应用才是关键。
在以MD为基础的app设计中,经常会出现以下结构(如图1)
在Android 4.0和material design设计规范中都专门对选项卡进行了说明,但两者的说法不同。
在Android 4.0中,选项卡tabs属于操作栏的一部分,可以很轻松探索 app 中的不同功能,或浏览不同分类的数据集,就是说tabs选项卡是可以作为导航使用的,类似于iOS的标签栏,只是iOS放在屏幕底部,安卓是放在屏幕顶端(如上图2)。
但在material design中,tabs 的作用是将大量关联的数据或者选项划分成更易理解的分组,虽然很容易让人联想到导航,但其本身并不是用来导航的。每个tab的内容应该互相关联并且是在同 一个主题下(如下图)。图中出行方式可以通过tab划分成多种方式,但是搜索、指南、设置却完全属于不同的功能导航。
如此看来,两种规范似乎是相互冲突的,而且只要留心一下你会发现,现在市场上经常是这两种形式都有。googel官方比较推崇应用结构是:左侧导航抽屉+应用栏+tabs(Tab可选),但是同一种结构却有两种不同表现方式。
侧边栏导航作为应用的主导航,头屏显示应用最重要的功能或内容,如果在较低层级中有多个平行相关视图,可以用Tab结构(当然也可以没有)。这种结 构的关键是主要功能或内容很突出,所以头屏最大化显示,而其他功能相对较弱,不需要频繁切换侧边栏导航(如下图)。谷歌发布的inbox邮箱,左侧导航栏作为主导航,默认显示收件箱页面,用户最常用也最重要的功能是查看收件箱,至于其他的发件箱、垃圾邮件等都可以放在导航抽屉内收起。googel图书顶部是应用栏+tabs结构,此处Tab强调的是在同一主题下的不同归类,而不是导航。
或许是受4.0规范的影响,在左侧导航抽 屉+应用栏+tabs的应用结构中,Tab作为应用的主导航,而左侧抽屉作为辅导航,收纳一些用户不常使用的功能,像用户中心、设置、反馈等。这种结构适 合那些多个相同等级的功能视图需要频繁切换的app,且只需要手指左右滑动就能快速切换Tab视图,这将大大提高应用使用效率。如下图所示,虽然是概念设计(主要是国内安卓应用喜欢延续iOS风格,将Tab放在屏幕底部,米找到合适的例子,且MD没有被普遍应用),但很适合该场景下的示例。这款产品类似于微信,将主要功能导航放在顶部,实现快速切换,侧边抽屉导航放置收藏、状态、设置等次要功能。
以上两种方式并不冲突,关键是看你应用的功能内容。如果你的应用核心功能很突出,且不需要其他功能频繁切换,就选择第一种;如果你的应用有两个或者两个以上相同重要的功能模块,且需要频繁切换,比如微信的即时聊天和朋友圈,那就尝试第二种。
Android部分暂时就到这里,来看看iOS。如果展开来讲,体系太庞大,暂且用一张图表示,虽然都是很基础的内容。
另外,Android和IOS很明显的差异是层级返回和编辑选择。
IOS平台没有实体返回按键,所以涉及层级间的导航,app界面本身一定要有返回按钮,而实体home键只负责应用退出。Android平台有物理 返回按键,且点击返回的是动作流。比如,在搜索界面,点击搜索框调出软键盘,再点返回按键,不是返回上一页,而是收回弹出的软键盘,它强调的是返回上一个 动作的界面,而非层级关系。在Android平台上的app,如果应用本身含有返回按钮,返回的是上一层级,设计的是层级间的导航。另外,在安卓app的首页点击返回按键,就是退出应用。可看如下关系图
对于编辑选择功能,IOS有明确的入口,通常在导航栏 上有编辑按钮,点击后进入编辑模式,通常可以多选,同时底部或顶部会增加工具栏,用来处理多选内容。当然也可以单选删除,通过点按向左滑动删除,或者是点 击按钮从底部呼出操作菜单,逐个删除。但Android是通过长安方式进入编辑模式,此时操作栏被一个临时情景操作栏覆盖(情景操作栏可以覆盖顶部操作栏 和底部操作栏),界面内容允许单个或多个操作(如下图)
以上部分其实都是一些平台规范总结,将区别大且重要部分整理出来,也是为了方便阅读查看,后期会持续更新一些其他交互内容。
作者:butter
来源:jianshu
规范的命名方式可以提高客户端程序员的开发效率和团队协作。个人觉得标识符命名原则:尽可能的用最少的字符而又能完整的表达标识符的含义。
切图命名英文缩写三个原则:
1 较短的单词可通过去掉“元音”形成缩写
2 较长的单词可取单词的头几个字母形成缩写
3 此外还有一些约定成俗的英文单词缩写.
IOS和Android是移动操作系统中最大的两个阵营。毫无疑问,这两个系统可以说是手机行业里的一个奇迹,并且也在逐渐变得完善。
一部智能设备撇开众多的功能不说,一套不错的UI界面和良好的交互模式是一部智能机的基础。如果没有有用的用户界面,那么设备也不过是一块没有作用的电路板。
尽管这两个操作系统更新迭代的时间有些漫长,但如果你压缩每代系统更新的总时间来看,你就会发现IOS和Android在UI上面的变化还是挺大的。
在这里,我们以UI设计理念进行对比,一起来看看这两个操作系统随时间的演变。
IOS和Android在UI上的开发
初涉移动端设计和开发的同学们,基本都会在尺寸问题上纠结好一阵子才能摸到头绪。我也花了很长时间才弄明白,感觉有必要写一篇足够通俗易懂的教程来帮助大家。从原理说起,理清关于尺寸的所有细节。由于是写给初学者的,所以不要嫌我啰嗦。
首先说现象,大家都知道移动端设备屏幕尺寸非常多,碎片化严重。尤其是Android,你会听到很多种分辨率:480×800, 480×854, 540×960, 720×1280, 1080×1920,而且还有传说中的2K屏。近年来iPhone的碎片化也加剧了:640×960, 640×1136, 750×1334, 1242×2208。
不要被这些尺寸吓倒。实际上大部分的app和移动端网页,在各种尺寸的屏幕上都能正常显示。说明尺寸的问题一定有解决方法,而且有规律可循。
iOS 8 的设计原则在我的理解是:
而要讲 Android 5.0 设计原则就必须说到谷歌推出的全新设计语言 Material Design 。Material Design 的设计原则在我的理解里是这样的:
蓝蓝 http://www.lanlanwork.com