热门资讯 点击: 2013-03-05
Android插件化的思考——仿QQ一键换肤,思考比实现更重要!
Android插件化的思考——仿QQ一键
换肤,思考比实现更重要!
关于QQ的换肤,他们的实现思路我不是很清楚,但是你可以看一下这张换肤的截图
我们想使用哪个主题就直接下载就好了,这一实现的过程我们大致的可以猜想:
首选是下载到本地指定文件夹,然后通过插件加载到我们的apk,最后应用为皮肤,逻辑大致是这样的逻辑了,那我们是不是应该动动手啊动动脑?
首选我们新建一个工程好了——
PlugInSample
一.实现思路
其实说起来,这个插件的实现思路,确实是比较的麻烦,思来想去,还是一种办法比较靠谱,首先,我们刻意去获取手机上所有的安装的/未安装的程序,过滤掉没用的,留下我们的插件apk,我们的插件apk怎么去辨别呢?我们可用通过设置sharedUserId,然后用实体类把插件名称和包名保存下来,有了包名,就比较好说了,我们可用获取插件的上下文,也就是createPackageContext,然后就可以做点坏事了,我们可以去剖析我们的R文件
因为R文件里面都是静态的原因,我们很容易联想到反射机制,是的,我们可以再一次过
滤掉无用的信息,通过我们的PathClassLoader去加载,访问我们的内加载器反射到我们的图片ID,也就是后面的那段数字,然后,嘿嘿,就可以使用了,是不是思路比较清晰了?这里要注意的就是图片命名统一,这样就比较号过来,那具体我们应该怎么做?
二.PlugIn主程序
我们写一个Spinner,每次切换就直接换肤怎么样?OK,每次换的时候就从插件APK里加载我们的图片资源,看起来是比较顺畅的逻辑,那我们具体该怎么做呢?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/mLinearLayout"
xmlns:android="
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Spinner
android:id="@+id/mSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
1.初始化
/**
* 初始化View
*/
private void initView() {
//初始化控件
mSpinner = (Spinner) findViewById(R.id.mSpinner);
}
当然,我这刚应用就一个View,但是实际开发当中可不止,所以步骤一定要明了
2.获取所有的插件
/**
* 获取手机里的插件
*
* @return
*/
private List<PlugInBean> findPlugIn() {
mList = new ArrayList<>();
//获取相关信息
PackageManager mPackageManager = getPackageManager();
//获取卸载/未安装的安装包信息
List<PackageInfo> mUninstallPackage = mPackageManager.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES); //遍历拿到我们的信息
for (PackageInfo info : mUninstallPackage) {
String pkgNmae = info.packageName;
//获取shareId,根据id判断是否是我们的ID
String shareUserId = info.sharedUserId;
if (!TextUtils.isEmpty(shareUserId)) {{android仿qq写说说}.
//如果id相同
if (shareUserId.equals("com.liuguilin.share")) {
//且排除自己的包名
if (!pkgNmae.equals(getPackageName())) {
//这个就是我们的插件了
String lable = mPackageManager.getApplicationLabel(info.applicationInfo).toString();
PlugInBean bean = new PlugInBean();
bean.setLabelNmae(lable);
bean.setPackagNmae(pkgNmae);
mList.add(bean);
}
}
}
}
return mList;
}
这里就是过滤了一下,通过sharedUserId去拿到我们的插件APK了,然后就可以拿到我们的包名和应用名,他返回给我们一个数据集
//所有的插件
List<PlugInBean> allPlugIn = findPlugIn();
3.加载皮肤数据
/**
* 加载皮肤
*
* @param allPlugIn
*/
private void LoadSkin(List<PlugInBean> allPlugIn) {
//遍历
for (PlugInBean bean : allPlugIn) {
HashMap<String, Object> mMap = new HashMap<>();
mMap.put("lable", bean.getLabelNmae());
mMap.put("package", bean.getPackagNmae());
mData.add(mMap);
}
//建立Adapter并且绑定数据源
mAdapter = new SimpleAdapter(this, mData, android.R.layout.simple_list_item_1, new String[]{"lable"}, new int[]{android.R.id.text1});
//设置数据
mSpinner.setAdapter(mAdapter);
//设置监听事件
mSpinner.setOnItemSelectedListener(this);
}
我们通过刚才的数据集便可以把我们拿到的数据给直接显示出来了,这里其实可以判断一下size是否为0,如果为0的话也就没有插件,OK,我们设置adapter和监听,做到这里,其实你可以运行一下,虽然我们现在什么都没有,我们要做的还有很多
4.获取插件Context{android仿qq写说说}.
/**
* 选中监听事件
*
* @param adapterView
* @param view
* @param i
* @param l
*/
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { PlugInBean bean = mList.get(i);
//插件的包名
String packageNmae = bean.getPackagNmae();
Context mContext = null;
try {
//无视警告 访问代码
mContext = createPackageContext(packageNmae, CONTEXT_IGNORE_SECURITY | CONTEXT_INCLUDE_CODE);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
//获取图片
getImg(packageNmae, mContext);
//通过ID加载插件的图片
getWindow().setBackgroundDrawable(mContext.getResources().getDrawable(mListId.get(i))); }
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
这里的代码就比较有意思,一定要仔细看,我们首先拿到选中的item的包名,通过我们的createPackageContext拿到我们的上下文,通过这两个我们可用拿到我们的资源ID,也就是R清单里面的ID,然后直接设置window的背景,这里为了好看才设置window的背景,实际上你要设置的是你根布局的背景,那好,我们来看一下如何通过插件的上下文和包名拿到R清单的资源ID
5.获取插件图片 / 返回图片R文件ID / 反射R文件
/**
* 获取插件图片 / 返回图片R文件ID / 反射R文件
*
* @param packageNmae
* @param mContext
*/
private void getImg(String packageNmae, Context mContext) {
//类加载器反射插件
PathClassLoader pathClass = new PathClassLoader(mContext.getPackageResourcePath(), ClassLoader.getSystemClassLoader()); //反射 $ 访问类加载器
try {
Class<?> forNmae = Class.forName(packageNmae + ".R$drawable", true, pathClass);
//拿到所有图片的id
Field[] files = forNmae.getDeclaredFields();
for (Field id : files) {
//过滤 / 这里的命名可以注意一下
if (id.getName().startsWith("img")) {
int drawId = 0;
////这就是我们图片R下的ID
drawId = id.getInt(R.drawable.class);
mListId.add(drawId);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
Android模仿QQ的左右滑动切换界面和下拉更新的效果
Android模仿QQ的左右滑动切换界面和下拉更新的效果
因为功能还没有完全实现,所以效果不是太好,不过呢,还是能实现,左右滑动时候切换界面和显示QQ好友列表的简单功能!!好了,废话不多说了看看实现的过程吧!
1.首先看看布局
主布局main.xml 1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:Android="
3. android:layout_width="fill_parent"
4. android:layout_height="fill_parent"
5. android:orientation="vertical" >
6.
7. <HorizontalScrollView
8. android:id="@+id/horizontalscrollview"
9. android:layout_width="match_parent"
10. android:layout_height="wrap_content"
11. android:background="@drawable/item"
12. android:fadingEdge="@null"
13. android:scrollbars="none" >
14.
15. <LinearLayout
16. android:id="@+id/linearlayout"
17. android:layout_width="match_parent"
18. android:layout_height="match_parent"
19. android:orientation="horizontal"
20. >
21. </LinearLayout>
22. </HorizontalScrollView>
23.
24. <android.support.v4.view.ViewPager
25. android:id="@+id/viewpaper"
26. android:layout_width="fill_parent"{android仿qq写说说}.
27. android:layout_height="match_parent"
28. android:layout_weight="1" >
29. </android.support.v4.view.ViewPager>
31. </LinearLayout>
2,接着看看QQonline.xml 1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="
3. android:layout_width="fill_parent"
4. android:layout_height="fill_parent"
5. android:orientation="vertical"
6. android:background="@drawable/image2">
7.
8.
9. <ExpandableListView
10. android:id="@+id/elistview"
11. android:layout_width="fill_parent"
12. android:layout_height="wrap_content"
13. android:layout_marginLeft="5dp"
14.
15.
16. />
17.
18. </LinearLayout>
3.接着看看下拉更新的布局pullrefresh.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="
3. android:layout_width="fill_parent"
4. android:layout_height="fill_parent"
5. android:background="@drawable/image1"
6. android:orientation="vertical" >
7.
8. <com.wang.pullrefresh.MyListView
9. android:id="@+id/listView"
10. android:layout_width="fill_parent"
11. android:layout_height="fill_parent" />
13.
14. </LinearLayout>
4.下拉更新过程实现的布局refresh.xml 1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="
3. android:layout_width="fill_parent"
4. android:layout_height="wrap_content" >
5.
6. <RelativeLayout
7. android:id="@+id/head_contentLayout"
8. android:layout_width="fill_parent"
9. android:layout_height="wrap_content"
10. android:paddingLeft="30dp" >
11.
12. <FrameLayout
13. android:layout_width="wrap_content"
14. android:layout_height="wrap_content"
15. android:layout_alignParentLeft="true"
16. android:layout_centerVertical="true" >
17.
18. <ImageView
19. android:id="@+id/head_arrowImageView"
20. android:layout_width="wrap_content"
21. android:layout_height="wrap_content"
22. android:layout_gravity="center"
23. android:src="@drawable/down" />
24.
25. <ProgressBar
26. android:id="@+id/head_progressBar"
27. style="?android:attr/progressBarStyleSmall"
28. android:layout_width="wrap_content"
29. android:layout_height="wrap_content"
30. android:layout_gravity="center"{android仿qq写说说}.
31. android:visibility="gone" />
32. </FrameLayout>
33.
34. <LinearLayout
35. android:layout_width="wrap_content"
36. android:layout_height="wrap_content"
37. android:layout_centerHorizontal="true"
38. android:gravity="center_horizontal"
39. android:orientation="vertical" >
40.
41. <TextView 42. android:id="@+id/head_tipsTextView"
43. android:layout_width="wrap_content"
44. android:layout_height="wrap_content"
45. android:text="下拉可以刷新"
46. android:textSize="15dp" />
47.
48. <TextView
49. android:id="@+id/head_lastUpdatedTextView"
50. android:layout_width="wrap_content"
51. android:layout_height="wrap_content"
52. android:text="上次更新时间:"
53. android:textSize="12dp" />
54. </LinearLayout>
55. </RelativeLayout>
56.
57. </LinearLayout>
5.下拉更新的列表显示的布局list_item.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="
3. android:layout_width="match_parent"
4. android:layout_height="wrap_content"
5. android:gravity="center_vertical"
6. android:orientation="horizontal" >
7.
8. <ImageView
9. android:id="@+id/imageView_item"
10. android:layout_width="60dp"
11. android:layout_height="60dp"
12. android:layout_marginLeft="5dp"
13. android:src="@drawable/qq" />
14.
15. <TextView
16. android:id="@+id/textView_item"
17. android:layout_width="wrap_content"
18. android:layout_height="wrap_content"
19. android:layout_marginLeft="10dp"
20. android:textColor="#FFFFFF"
21. />
22.
23. </LinearLayout>
6.接着看看还没有完善的QQ聊天信息的布局main3.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="
3. android:layout_width="fill_parent"
4. android:layout_height="fill_parent"
5. android:orientation="vertical"
6. android:background="@drawable/image3">
7.
8.
9.
10. </LinearLayout>
7.接着看看主活动的实现过程ViewPaper1Activity.java
1. package com.wang;
2.
3. import java.util.ArrayList;
4.
5. import android.app.ActivityGroup;
6. import android.content.Intent;
QQ空间心情说说:回忆太痛,只因相遇太美
QQ空间心情说说:回忆太痛,只因相遇太美
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.写在空间里的文字,不是感伤,祭奠,宣泄,只是记录,在一时一刻某时某刻的某种心情某种情感,这种东西,过了时间点,再也写不出。
经典的QQ空间说说心情 我欺骗了好多人,可是就是骗不了自己
01 我那么爱你,却没有勇气把你留下。 02 你的爱像新鲜的柠檬,这滋味酸甜可口,爱有一千零一种,你给的是与众不同、 03 你走了就算了,但你为什么要拿他来恶心我,他算个什么东西。 04 -我现在对你真情真意、以后不知道换来的是些什么,不知道是好是坏。 05 每次我都是那么的听话 、你却一句也不会听我的 06 当金钱站起来说话时,所有的真理都沉默了。 07 你说你不能失去。为什么离开的时候那么干脆利落。 08 想你,我不停的想你、可是又能怎么样?你爱的人已经不是我了。 09 - 非常想离开这个却又不能离开这个家,你们谁懂这样的无奈呐, // 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 蹉跎岁月,我只想对你说;老婆,我爱你!
本文由《文章马伊琍网》/ 负责整理首发
QQ空间说说心情短语 我们孤独的表演着自己、
01 我很好,不吵不闹不炫耀,不要委屈不要嘲笑,也不要别人知道。
02 ミ一个人在雨中默默哭泣,那种苦涩的滋味有谁能懂.╭? 03 转弯只为了遇见你、却忘了你也会转弯。 04 你已成为过去,没有你我的未来会更好。 05 - 生命是一场寂寥的马戏,我们带着面具欺骗自己、{android仿qq写说说}.
06 ﹌年轻不是你玩的理由,而是你奋斗的资本// 07 -如果有一天。我失踪了ヾ 那么,谁会满世界找我
qq空间说说意境句子
你不一定过得比现在快乐。时光倒流的前提,一定是要让我保留这些年的记忆。
关于你的回忆总是要事过境迁后才变得更加清晰。
记得你总是对我说,现在这样就挺好的。始终跟你以同样的速度前行,始终隔着一段长度不变的距离。始终以你觉得最适合的身份等待在你的影子里。这样多的始终积累到现在,我恍然间惊觉,其实我们根本不曾前行过。而是只有一个向右箭头的时间轴在我们脚下静静延伸,渐渐眺望不见端点。在兜兜转转踯踯躇躇期期艾艾之间我已经累了。我惊异于自己不可思议的执著,更惊异于这份执著不可思议地简单消逝。我不敢直面的终究是我自己而不是你。你期待的是不是我从身后追上去,再次面对你。我不想再猜了。虽然我曾经那么期待你能转过身,再次给我那个初遇时的笑容。
既然现在的你不是以前的你,那么,现在的我,也不想做以前的我了。
那个夏天就这样淡出了生命,仅仅消失为记忆的一部分。
那么盛开在年华里的遥远夜晚,是你无论如何坚持都回不到的过往。
如果真的是把一无所有作为起点,那么之后的就是获得,进而好好珍惜了吧。
死亡只能带走生命,不能带走灵魂留下的痕迹。
岁月从指间流淌着,我感觉到自己的星宿从轨迹中缓缓陨落。
所谓秘密,是那些注定无法分享的事情。
"所谓幸福,华丽空虚。眼底浮花,只是刹那。
条看不见的线就分割出永远不能跨越的距离,一边是昨天,一边是今天。
童话已经结束,遗忘就是幸福。
忘却,是最无奈的爱。
我很好,不吵不闹不炫耀,不要委屈不要嘲笑,也不需要别人知道。
我还在原地等你,你却已经忘记曾来过这里。
我决定不再流泪,就像你决定要离开我一般地坚定。
我们经过那么多考验,最后还是回到了原点……
我伸开自己的手在眼前,比想象中还要空。
我失恋了,你怎么可以把我弄丢了。
我是好人,别伤害我。
我忘记了无论怎样面向阳光生长,依旧会有阴影留在身后。如影随形。
我想用缩小电筒把思念变小,小到我再也看不见。用放大电筒把心脏放大,大到足以抵抗一切忧伤。可更幼稚的是我,我忘了即使你是野比大雄,我也不会是你的哆啦a梦。竹蜻蜓没电了,于是我也无法飞翔——在你的世界里。
我一直在努力的做一件事,我想让别人看到我的成绩。我很用心的在做某一件事,我想让别人看到我的真诚。
有些事情,依靠追悔又怎么追得回来?
在那一刻,我仿佛看见整个世界崩溃在我的面前。废墟中那一片片的瓦砖都刻有鲜活的记忆,现在安静地贴在大地上,即便我有多小心保持行走的安静,终究会发现,自己只是一个被记忆放逐的人。
这样的夏天,于生命留下的是一溜狭长而落寂的影子。在影子的深处,某些已经再也看不到的面孔偶尔还会闪烁起来。背影永远是浓的像油墨一般的黑暗。你正在离开。身影的轮廓的颜色已经迅速地退进了那片浓墨之中去。可是眉眼中的灿亮。却鲜明得融不进夜色。我想起来,便会觉得。这是一副适合搁置在记忆里的笑容。
终究会有一天,你的手会挽着另一个人的手。而站在我身边的也不再是你。
1、有没有那么一瞬间,你想过要和你的闺蜜同一天出嫁。
2、好朋友就像是星星,你不一定总是能见到他们。但你知道,他们会一直在那里。
3、闺蜜就是当你被别人欺负的时候,愿意不顾一切为你挺身而出的人。
4、闺蜜你记住:他若折断你的翅膀,我必亲手毁了他的天堂,有我在没人敢伤害你。
5、我有一个很好的女朋友,我们不是情侣,我们不是LES,但是我爱她。