在Android系统上启动知乎app时会唤醒微信是啥原因?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Android系统上启动知乎app时会唤醒微信是啥原因?相关的知识,希望对你有一定的参考价值。
知乎调用微信sdk中分享的相关接口,微信sdk的相关接口里面,给微信发送了一个广播,微信app就被唤醒了,这不是知乎的主观行为,而是微信的(而且结合实际的分析来看,这个应该也算是正常的功能)。1首先说一下app的被唤醒(自启动)机制。
app自启动,基本上都是依靠android的广播来实现的,而且是静态注册的广播(在AndroidManifest.xml文件中进行配置的广播),发送广播的方法在一般情况下是sendBroadcast。
2按照惯例,反编译一下微信apk,然后搜索一下它能够由哪些静态广播进行唤醒,同时抓取广播相关的log。
结合微信的AndroidManifest.xml文件以及抓取的log,可以知道相关的BroadcastReceiver是EntryReceiver,相关的action为
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER
从其名称上看,是和注册/注销相关,具体接收到广播之后做了哪些处理,这些就不赘述了。
3接下来分析知乎的代码,搜索一下知乎反编译之后的smali文件(sendBroadcast),其中只有一条是和微信相关的 参考技术A 本回答信息来自针对微信Android客户端以及知乎Android客户端的分析。
我手机上装了一键清理的软件,平时从来不让微信在后台运行,但是每当打开知乎,不出三秒,微信消息就来了,消息并不固定,只是感觉微信被打开了,我在想知乎是不是跟微信合作,后台打开微信,然后以此来赚钱的呢?
首先针对题主的疑问,准备的回答:不是
实际的情况是,知乎调用微信sdk中分享的相关接口,微信sdk的相关接口里面,给微信发送了一个广播,微信app就被唤醒了,这不是知乎的主观行为,而是微信的(而且结合实际的分析来看,这个应该也算是正常的功能)。
以下是详细分析:
1 首先说一下app的被唤醒(自启动)机制。
app自启动,基本上都是依靠Android的广播来实现的,而且是静态注册的广播(在AndroidManifest.xml文件中进行配置的广播),发送广播的方法在一般情况下是sendBroadcast。
2 按照惯例,反编译一下微信apk,然后搜索一下它能够由哪些静态广播进行唤醒,同时抓取广播相关的log。
结合微信的AndroidManifest.xml文件以及抓取的log,可以知道相关的BroadcastReceiver是EntryReceiver,相关的action 为
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER
从其名称上看,是和注册/注销相关,具体接收到广播之后做了哪些处理,这些就不赘述了。
I/ActivityManager( 1107): Start proc com.tencent.mm for broadcast com.tencent.mm/.plugin.base.stub.WXEntryActivity$EntryReceiver: pid=28779 uid=10131 gids=50131, 3003, 1028, 1015, 3002, 3001
<receiver android:name="com.tencent.mm.plugin.base.stub.WXEntryActivity$EntryReceiver">
<intent-filter>
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER"/>
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER"/>
</intent-filter>
3 接下来分析知乎的代码
搜索一下知乎反编译之后的smali文件(sendBroadcast),其中只有一条是和微信相关的
zhihu_2.0.3_176/smali/com/tencent/mm/sdk/openapi/j.smali: invoke-virtual v0, v4, v1, Landroid/content/Context;->sendBroadcast(Landroid/content/Intent;Ljava/lang/String;)V
再看一下反编译的java文件,能够比较清楚的看到,就是利用com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER
这个action来进行注册,检查一些必要的信息。
根据这些信息,结合微信和知乎反编译之后的文件,已经可以完整的分析具体发生了哪些事情了。
com.tencent.mm.sdk.openapi.j
public final boolean a(String paramString)
if (!b("com.tencent.mm"))
com.tencent.mm.sdk.platformtools.a.a("MicroMsg.SDK.WXApiImplV10", "register app failed for wechat app signature check failed");
return false;
this.b = paramString;
com.tencent.mm.sdk.platformtools.a.b("MicroMsg.SDK.WXApiImplV10", "register app " + this.a.getPackageName());
Context localContext = this.a;
String str1 = "weixin://registerapp?appid=" + this.b;
String str2 = "com.tencent.mm" + ".permission.MM_MESSAGE";
Intent localIntent = new Intent("com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER");
String str3 = localContext.getPackageName();
localIntent.putExtra("_mmessage_sdkVersion", 553910273);
localIntent.putExtra("_mmessage_appPackage", str3);
localIntent.putExtra("_mmessage_content", str1);
localIntent.putExtra("_mmessage_checksum", b.a(str1, str3));
localContext.sendBroadcast(localIntent, str2);
com.tencent.mm.sdk.platformtools.a.b("MicroMsg.SDK.MMessage", "send mm message, intent=" + localIntent + ", perm=" + str2);
return true;
4 最后,因为偷懒,所以我只是大概的静态分析了相关代码,没发现知乎和微信做了什么丧失的事情,然后大概加了段log check了一下,从中也可以看出的确是和分享有关,至于使用时机及频率是否合适,这个和问题没什么关系,不做讨论。
D/hillwind( 5766): java.lang.Throwable
D/hillwind( 5766): at com.hillwind.android.util.RLog.printStackTrace(RLog.java:11)
D/hillwind( 5766): at com.tencent.mm.sdk.openapi.j.a(Unknown Source)
D/hillwind( 5766): at com.zhihu.android.util.af.b(WeChatHelper.java:43)
D/hillwind( 5766): at com.zhihu.android.widget.a.b(ActivityChooserModel.java:721)
D/hillwind( 5766): at com.zhihu.android.widget.ShareActionProvider.setShareIntent(ShareActionProvider.java:98)
D/hillwind( 5766): at com.zhihu.android.ui.fragment.bx.a(QuestionViewerFragment.java:221)
D/hillwind( 5766): at android.support.v4.app.j.a(FragmentManager.java:1973)
D/hillwind( 5766): at android.support.v4.app.g.onCreatePanelMenu(FragmentActivity.java:226)
D/hillwind( 5766): at android.support.v7.a.b.a(ActionBarActivity.java:233)
D/hillwind( 5766): at android.support.v7.a.g.a(ActionBarActivityDelegateICS.java:146)
D/hillwind( 5766): at android.support.v7.a.b.onCreatePanelMenu(ActionBarActivity.java:200)
D/hillwind( 5766): at android.support.v7.a.g$a.onCreatePanelMenu(ActionBarActivityDelegateICS.java:293)
D/hillwind( 5766): at com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:472)
D/hillwind( 5766): at com.android.internal.policy.impl.PhoneWindow.doInvalidatePanelMenu(PhoneWindow.java:878)
D/hillwind( 5766): at com.android.internal.policy.impl.PhoneWindow$1.run(PhoneWindow.java:257)
D/hillwind( 5766): at android.os.Handler.handleCallback(Handler.java:733)
D/hillwind( 5766): at android.os.Handler.dispatchMessage(Handler.java:95)
D/hillwind( 5766): at android.os.Looper.loop(Looper.java:136)
D/hillwind( 5766): at android.app.ActivityThread.main(ActivityThread.java:5140)
D/hillwind( 5766): at java.lang.reflect.Method.invokeNative(Native Method)
D/hillwind( 5766): at java.lang.reflect.Method.invoke(Method.java:515)
D/hillwind( 5766): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
D/hillwind( 5766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
D/hillwind( 5766): at dalvik.system.NativeStart.main(Native Method) 参考技术B
知乎调用微信sdk中分享的相关接口,微信sdk的相关接口里面,给微信发送了一个广播,微信app就被唤醒了,这不是知乎的主观行为,而是微信的(而且结合实际的分析来看,这个应该也算是正常的功能)。
1 首先说一下app的被唤醒(自启动)机制。
app自启动,基本上都是依靠Android的广播来实现的,而且是静态注册的广播(在AndroidManifest.xml文件中进行配置的广播),发送广播的方法在一般情况下是sendBroadcast。
2 按照惯例,反编译一下微信apk,然后搜索一下它能够由哪些静态广播进行唤醒,同时抓取广播相关的log。
结合微信的AndroidManifest.xml文件以及抓取的log,可以知道相关的BroadcastReceiver是EntryReceiver,相关的action 为
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER
从其名称上看,是和注册/注销相关,具体接收到广播之后做了哪些处理,这些就不赘述了。
3 接下来分析知乎的代码,搜索一下知乎反编译之后的smali文件(sendBroadcast),其中只有一条是和微信相关的
参考技术C本回答信息来自针对微信Android客户端以及知乎Android客户端的分析。
我手机上装了一键清理的软件,平时从来不让微信在后台运行,但是每当打开知乎,不出三秒,微信消息就来了,消息并不固定,只是感觉微信被打开了,我在想知乎是不是跟微信合作,后台打开微信,然后以此来赚钱的呢?
首先针对题主的疑问,准备的回答:不是
实际的情况是,知乎调用微信sdk中分享的相关接口,微信sdk的相关接口里面,给微信发送了一个广播,微信app就被唤醒了,这不是知乎的主观行为,而是微信的(而且结合实际的分析来看,这个应该也算是正常的功能)。
以下是详细分析:
1 首先说一下app的被唤醒(自启动)机制。
app自启动,基本上都是依靠Android的广播来实现的,而且是静态注册的广播(在AndroidManifest.xml文件中进行配置的广播),发送广播的方法在一般情况下是sendBroadcast。
2 按照惯例,反编译一下微信apk,然后搜索一下它能够由哪些静态广播进行唤醒,同时抓取广播相关的log。
结合微信的AndroidManifest.xml文件以及抓取的log,可以知道相关的BroadcastReceiver是EntryReceiver,相关的action 为
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER
com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER
从其名称上看,是和注册/注销相关,具体接收到广播之后做了哪些处理,这些就不赘述了。
I/ActivityManager( 1107): Start proc com.tencent.mm for broadcast com.tencent.mm/.plugin.base.stub.WXEntryActivity$EntryReceiver: pid=28779 uid=10131 gids=50131, 3003, 1028, 1015, 3002, 3001
<receiver android:name="com.tencent.mm.plugin.base.stub.WXEntryActivity$EntryReceiver">
<intent-filter>
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER"/>
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER"/>
</intent-filter>
3 接下来分析知乎的代码
搜索一下知乎反编译之后的smali文件(sendBroadcast),其中只有一条是和微信相关的
zhihu_2.0.3_176/smali/com/tencent/mm/sdk/openapi/j.smali: invoke-virtual v0, v4, v1, Landroid/content/Context;->sendBroadcast(Landroid/content/Intent;Ljava/lang/String;)V
再看一下反编译的java文件,能够比较清楚的看到,就是利用com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER
这个action来进行注册,检查一些必要的信息。
根据这些信息,结合微信和知乎反编译之后的文件,已经可以完整的分析具体发生了哪些事情了。
com.tencent.mm.sdk.openapi.j
public final boolean a(String paramString)
if (!b("com.tencent.mm"))
com.tencent.mm.sdk.platformtools.a.a("MicroMsg.SDK.WXApiImplV10", "register app failed for wechat app signature check failed");
return false;
this.b = paramString;
com.tencent.mm.sdk.platformtools.a.b("MicroMsg.SDK.WXApiImplV10", "register app " + this.a.getPackageName());
Context localContext = this.a;
String str1 = "weixin://registerapp?appid=" + this.b;
String str2 = "com.tencent.mm" + ".permission.MM_MESSAGE";
Intent localIntent = new Intent("com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER");
String str3 = localContext.getPackageName();
localIntent.putExtra("_mmessage_sdkVersion", 553910273);
localIntent.putExtra("_mmessage_appPackage", str3);
localIntent.putExtra("_mmessage_content", str1);
localIntent.putExtra("_mmessage_checksum", b.a(str1, str3));
localContext.sendBroadcast(localIntent, str2);
com.tencent.mm.sdk.platformtools.a.b("MicroMsg.SDK.MMessage", "send mm message, intent=" + localIntent + ", perm=" + str2);
return true;
4 最后,因为偷懒,所以我只是大概的静态分析了相关代码,没发现知乎和微信做了什么丧失的事情,然后大概加了段log check了一下,从中也可以看出的确是和分享有关,至于使用时机及频率是否合适,这个和问题没什么关系,不做讨论。
D/hillwind( 5766): java.lang.Throwable
D/hillwind( 5766): at com.hillwind.android.util.RLog.printStackTrace(RLog.java:11)
D/hillwind( 5766): at com.tencent.mm.sdk.openapi.j.a(Unknown Source)
D/hillwind( 5766): at com.zhihu.android.util.af.b(WeChatHelper.java:43)
D/hillwind( 5766): at com.zhihu.android.widget.a.b(ActivityChooserModel.java:721)
D/hillwind( 5766): at com.zhihu.android.widget.ShareActionProvider.setShareIntent(ShareActionProvider.java:98)
D/hillwind( 5766): at com.zhihu.android.ui.fragment.bx.a(QuestionViewerFragment.java:221)
D/hillwind( 5766): at android.support.v4.app.j.a(FragmentManager.java:1973)
D/hillwind( 5766): at android.support.v4.app.g.onCreatePanelMenu(FragmentActivity.java:226)
D/hillwind( 5766): at android.support.v7.a.b.a(ActionBarActivity.java:233)
D/hillwind( 5766): at android.support.v7.a.g.a(ActionBarActivityDelegateICS.java:146)
D/hillwind( 5766): at android.support.v7.a.b.onCreatePanelMenu(ActionBarActivity.java:200)
D/hillwind( 5766): at android.support.v7.a.g$a.onCreatePanelMenu(ActionBarActivityDelegateICS.java:293)
D/hillwind( 5766): at com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:472)
D/hillwind( 5766): at com.android.internal.policy.impl.PhoneWindow.doInvalidatePanelMenu(PhoneWindow.java:878)
D/hillwind( 5766): at com.android.internal.policy.impl.PhoneWindow$1.run(PhoneWindow.java:257)
D/hillwind( 5766): at android.os.Handler.handleCallback(Handler.java:733)
D/hillwind( 5766): at android.os.Handler.dispatchMessage(Handler.java:95)
D/hillwind( 5766): at android.os.Looper.loop(Looper.java:136)
D/hillwind( 5766): at android.app.ActivityThread.main(ActivityThread.java:5140)
D/hillwind( 5766): at java.lang.reflect.Method.invokeNative(Native Method)
D/hillwind( 5766): at java.lang.reflect.Method.invoke(Method.java:515)
D/hillwind( 5766): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
D/hillwind( 5766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
D/hillwind( 5766): at dalvik.system.NativeStart.main(Native Method)
微信小程序开发日记——高仿知乎日报(上)
本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP
要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉
我将该教程分为以下三篇
- 微信小程序开发日记——高仿知乎日报(上)
- 微信小程序开发日记——高仿知乎日报(中)
- 微信小程序开发日记——高仿知乎日报(下)
三篇分别讲不同的组件和功能块
这篇要讲
- API分析
- 启动页
- 轮播图
- 日报列表
- 浮动按钮
- 侧滑菜单
API分析
以下是使用到的具体API,更加详细参数和返回结构可参照网上网友分享的 知乎日报-API-分析 ,在此就不做再次分析了。
启动界面图片
http://news-at.zhihu.com/api/4/start-image/{size}
参数 | 说明 |
---|---|
size | 图片尺寸,格式:宽*高。例如: 768*1024 |
获取刚进入应用时的显示封面,可以根据传递的尺寸参数来获取适配用户屏幕的封面。
获取最新日报
http://news-at.zhihu.com/api/4/news/latest
返回的数据用于日报的首页列表,首页的结构有上下部分,上部分是图片滑动模块,用于展示热门日报,下部分是首页日报列表,以上接口返回的数据有热门日报和首页日报
获取日报详细
http://news-at.zhihu.com/api/4/news/{id}
参数 | 说明 |
---|---|
id | 日报id |
在点击日报列表也的日报项时,需要跳转到日报详情页展示日报的具体信息,这个接口用来获取日报的展示封面和具体内容。
历史日报
http://news.at.zhihu.com/api/4/news/before/{date}
参数 | 说明 |
---|---|
date | 年月日格式时间yyyyMMdd,例如:20150903、20161202 |
这个接口也是用与首页列表的日报展示,但是不同的是此接口需要传一个日期参数,如20150804
格式。获取最新日报接口只能获取当天的日报列表,如果需要获取前天或者更久之前的日报,则需要这个接口单独获取。
日报额外信息
http://news-at.zhihu.com/api/4/story-extra/{id}
参数 | 说明 |
---|---|
id | 日报id |
在日报详情页面中,不仅要展示日报的内容,好需要额外获取此日报的评论数目和推荐人数等额外信息。
日报长评
http://news-at.zhihu.com/api/4/story/{id}/long-comments
参数 | 说明 |
---|---|
id | 日报id |
日报的评论页面展示长评用到的接口(没有找到分页参数,分页没有做)
日报短评
http://news-at.zhihu.com/api/4/story/{id}/short-comments
参数 | 说明 |
---|---|
id | 日报id |
日报的评论页面展示段评用到的接口(没有找到分页参数,分页没有做)
主题日报栏目列表
http://news-at.zhihu.com/api/4/themes
主页的侧边栏显示有主题日报的列表,需要通过这个接口获取主题日报栏目列表
主题日报具体内容列表
http://news-at.zhihu.com/api/4/theme/{themeId}
参数 | 说明 |
---|---|
themeId | 主题日报栏目id |
在主页侧栏点击主题日报进入主题日报的内容页,需要展示此主题日报下的日报列表。
启动页
作为一个仿制知乎日报的伪APP,高大上的启动封面是必须的,哈哈。启动页面很简单,请求一个应用启动封面接口,获取封面路径和版权信息。当进入页面,在onLoad
事件中获取屏幕的宽和高来请求适合尺寸的图片,在onReady
中请求加载图片,在请求成果之后,延迟2s进入首页,防止页面一闪而过。
onLoad: function( options ) {
var _this = this;
wx.getSystemInfo( {
success: function( res ) {
_this.setData( {
screenHeight: res.windowHeight,
screenWidth: res.windowWidth,
});
}
});
},
onReady: function() {
var _this = this;
var size = this.data.screenWidth + ‘*‘ + this.data.screenHeight;
requests.getSplashCover( size, ( data ) => {
_this.setData( { splash: data });
}, null, () => {
toIndexPage.call(_this);
});
}
/**
* 跳转到首页
*/
function toIndexPage() {
setTimeout( function() {
wx.redirectTo( {
url: ‘../index/index‘
});
}, 2000 );
}
轮播图
首页顶部需要用到轮播图来展示热门日报,小程序中的Swipe
组件可以实现。
<swiper class="index-swiper" indicator-dots="true" interval="10000">
<block wx:for="{{sliderData}}">
<swiper-item data-id="{{item.id}}" bindtap="toDetailPage">
<image mode="aspectFill" src="{{item.image}}" style="width:100%" />
<view class="mask"></view>
<view class="desc"><text>{{item.title}}</text></view>
</swiper-item>
</block>
</swiper>
所有的内容都必须要在swiper-item
标签中,因为我们的图片不止有一张,而是有多个热门日报信息,需要用循环来展示数据。这里需要指定的是image
里的属性mode
设置为aspectFill
是为了适应组件的宽度,这需要牺牲他的高度,即有可能裁剪,但这是最好的展示效果。toDetailPage
是点击事件,触发跳转到日报详情页。在跳转到日报详情页需要附带日报的id
过去,我们在循环列表的时候把当前日报的id
存到标签的data
中,用data-id
标识,这有点类似与html5中的data-*
API。当在这个标签上发生点击事件的时候,我们可以通过Event.currentTarget.dataset.id
来获取data-id
的值。
日报列表
列表的布局大同小异,不过这里的列表涉及到分页,我们可以毫不犹豫地使用scroll-view
组件,它的scrolltolower
是非常好用的,当组件滚动到底部就会触发这个事件。上次的小豆瓣图书也是使用了这个组件分页。不过这次的分页动画跟上次不一样,而是用一个附带旋转动画的刷新图标,使用官方的动画api来实现旋转。
<view class="refresh-block" wx:if="{{loadingMore}}">
<image animation="{{refreshAnimation}}" src="../../images/refresh.png"></image>
</view>
代码中有一个显眼的animation
属性,这个属性就是用来控制动画的。
/**
* 旋转上拉加载图标
*/
function updateRefreshIcon() {
var deg = 360;
var _this = this;
var animation = wx.createAnimation( {
duration: 1000
});
var timer = setInterval( function() {
if( !_this.data.loadingMore )
clearInterval( timer );
animation.rotateZ( deg ).step();
deg += 360;
_this.setData( {
refreshAnimation: animation.export()
})
}, 1000 );
}
当列表加载数据时,给动画设置一个时长duration
,然后按Z轴旋转,即垂直方向旋转rotateZ
,每次旋转360度,周期是1000毫秒。
列表的布局跟上次的小豆瓣图书的结构差不多,用到了循环结构wx:for
和判断语句wx:if
、 wx:else
来控制不同的展示方向。
<view class="common-list">
<block wx:for="{{pageData}}">
<view class="list-item {{item.images[0] ? ‘has-img‘: ‘‘}}" wx:if="{{item.type != 3}}" data-id="{{item.id}}" bindtap="toDetailPage">
<view class="content">
<text>{{item.title}}</text>
</view>
<image wx:if="{{item.images[0]}}" src="{{item.images[0]}}" class="cover"></image>
</view>
<view class="list-spliter" wx:else>
<text>{{item.title}}</text>
</view>
</block>
</view>
class="list-spliter"
这块是用来显示日期,列表中的日报只要不是同一天的记录,就在中间插入一条日期显示块。在列表项中有一个三元运算判断输出具体的class{{item.images[0] ? ‘has-img‘: ‘‘}}
,是因为列表中可能没有图片,因此需要判定当前有没有图片,没有图片就不添加class为has-img
来控制带有图片列表项的布局。
浮动按钮
因为小程序中没有侧栏组件,无法做到侧滑手势显示侧栏(本人发现touchstart事件和tap事件有冲突,无法实现出手势侧滑判断,所以没有用侧滑手势,可能是本人理解太浅了,没有发现解决方法,嘿嘿…),浮动按钮的样式参照了Android中的FloatAction经典按钮。可以浮动在界面上,还可以滑动到任意位置,背景为稍微透明。
<view class="float-action" bindtap="ballClickEvent" style="opacity: {{ballOpacity}};bottom:{{ballBottom}}px;right:{{ballRight}}px;" bindtouchmove="ballMoveEvent">
</view>
.float-action {
position: absolute;
bottom: 20px;
right: 30px;
width: 50px;
height: 50px;
border-radius: 50%;
box-shadow: 2px 2px 10px #AAA;
background: #1891D4;
z-index: 100;
}
按钮的样式随便弄了一下,宽高用了px
是因为后面的移动判断需要获取屏幕的宽高信息,这些信息的单位是px
。wxml绑定了点击事件和移动事件,点击事件是控制侧栏弹出,滑动事件是按钮移动。
//浮动球移动事件
ballMoveEvent: function( e ) {
var touchs = e.touches[ 0 ];
var pageX = touchs.pageX;
var pageY = touchs.pageY;
if( pageX < 25 ) return;
if( pageX > this.data.screenWidth - 25 ) return;
if( this.data.screenHeight - pageY <= 25 ) return;
if( pageY <= 25 ) return;
var x = this.data.screenWidth - pageX - 25;
var y = this.data.screenHeight - pageY - 25;
this.setData( {
ballBottom: y,
ballRight: x
});
}
touchmove
事件中的会传递一个event
参数,通过这个参数可以获取到当前手势滑动到的具体坐标信息e.touches[ 0 ]
侧滑菜单
侧滑菜单是一个经典APP布局方案,小程序中没有提供这个组件,甚是遗憾。不过实现起来也不是很难,但是总感觉有点别扭…
侧滑菜单的样式采用了固定定位的布局position: fixed
,默认隐藏与左侧,当点击浮动按钮时弹出,点击遮罩或者侧栏上边的关闭按钮时收回。侧栏的弹出和收回动画采用小程序提供的动画API。
<view class="slide-mask" style="display:{{maskDisplay}}" bindtap="slideCloseEvent"></view>
<view class="slide-menu" style="right: {{slideRight}}px;width: {{slideWidth}}px;height:{{slideHeight}}px;" animation="{{slideAnimation}}">
<icon type="cancel" size="30" class="close-btn" color="#FFF" bindtap="slideCloseEvent" />
<scroll-view scroll-y="true" style="height:100%;width:100%">
<view class="header">
<view class="userinfo">
<image src="../../images/avatar.png" class="avatar"></image>
<text>Oopsguy</text>
</view>
<view class="toolbar">
<view class="item">
<image src="../../images/fav.png"></image>
<text>收藏</text>
</view>
<view class="item" bindtap="toSettingPage">
<image src="../../images/setting.png"></image>
<text>设置</text>
</view>
</view>
</view>
<view class="menu-item home">
<text>首页</text>
</view>
<view class="slide-inner">
<block wx:for="{{themeData}}">
<view class="menu-item" data-id="{{item.id}}" bindtap="toThemePage">
<text>{{item.name}}</text>
<image src="../../images/plus.png"></image>
</view>
</block>
</view>
</scroll-view>
</view>
/*slide-menu*/
.slide-mask {
position: fixed;
width: 100%;
top: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, .3);
z-index: 800;
}
.slide-menu {
position: fixed;
top: 0;
background: #FFF;
z-index: 900;
}
/*.slide-menu .slide-inner {
padding: 40rpx;
}*/
.slide-menu .header {
background: #019DD6;
height: 200rpx;
color: #FFF;
padding: 20rpx 40rpx 0 40rpx;
}
.userinfo {
height: 80rpx;
line-height: 80rpx;
overflow: hidden;
}
.userinfo .avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 40rpx;
float: left;
}
.userinfo text {
float: left;
font-size: 35rpx;
}
.toolbar {
height: 100rpx;
padding-top: 25rpx;
line-height: 75rpx;
}
.toolbar .item {
width: 50%;
display: inline-block;
overflow: hidden;
text-align: center
}
.toolbar .item text {
display: inline-block;
font-size: 30rpx
}
.toolbar .item image {
display: inline-block;
position: relative;
top: 10rpx;
margin-right: 10rpx;
height: 50rpx;
width: 50rpx;
}
.slide-menu .menu-item {
position: relative;
height: 100rpx;
line-height: 100rpx;
padding: 0 40rpx;
font-size: 35rpx;
}
.slide-menu .menu-item:active {
background: #FAFAFA;
}
.slide-menu .menu-item image {
position: absolute;
top: 25rpx;
right: 40rpx;
width: 50rpx;
height: