android桌面悬浮窗仿QQ手机管家加速效果

主要还是用到了WindowManager对桌面悬浮进行管理.

需要一个火箭的悬浮窗 一个发射台悬浮窗  ,判断火箭是否放到了发射台,如果放上了,则使用AsyTask 慢慢将火箭的图片往上移.结束后., 返回原位.

1.打开activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.example.windowmanagerdemo1.MainActivity" >

<Button

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:id="@+id/btn_start"

android:text="start"

/>

</RelativeLayout>

就一个Button.

2.新建一个小悬浮窗的视图small_view.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

>

<LinearLayout

android:layout_width="60dp"

android:layout_height="20dp"

android:id="@+id/ll_smallView"

android:background="#000000"

android:orientation="vertical"

>

<TextView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:id="@+id/tv_percent"

android:textColor="#ffffff"

/>

</LinearLayout>

<ImageView

android:id="@+id/iv_recketImg"

android:layout_width="45dp"

android:layout_height="90dp"

android:src="@drawable/rocket"

android:visibility="gone"

/>

</FrameLayout>

在帧布局中放入一个LinearLayout,这个主要用来显示当前手机内存, 同时放入一个ImageView ,这个用于手指按下时显示出小火箭,平常小悬浮窗显示时则小火箭隐藏,当按住了小悬浮窗,则显示小火箭,隐藏悬浮窗.

3.新建 大悬浮窗视图 big_view.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="200dp"

android:layout_height="100dp"

android:id="@+id/ll_bigView"

android:background="#000000"

android:orientation="vertical" >

<Button

android:id="@+id/btn_close"

android:layout_width="100dp"

android:layout_height="40dp"

android:layout_gravity="center_horizontal"

android:text="关闭悬浮窗"

android:textColor="#ffffff"

/>

<Button

android:id="@+id/btn_back"

android:layout_width="100dp"

android:layout_height="40dp"

android:layout_gravity="center_horizontal"

android:text="返回"

android:textColor="#ffffff"

/>

</LinearLayout>

大悬浮窗 是在点击了小悬浮窗后显示的,里面就放了两个按钮.

4.新建发射台的视图  luncher.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

<ImageView

android:id="@+id/iv_luncher"

android:layout_width="200dp"

android:layout_height="88dp"

android:src="@drawable/launcher_bg_hold"

/>

</LinearLayout>

发射台视图只有一个ImageView.

5,新建一个FloatBigView.java 大悬浮窗的实体类

public class FloatBigView extends LinearLayout {

//记录大悬浮窗的高度

public static int ViewHeight;

//记录大悬浮窗的宽度

public static int ViewWidth;

public FloatBigView(final Context context) {

super(context);

LayoutInflater.from(context).inflate(R.layout.big_view, this);

View view=findViewById(R.id.ll_bigView);

ViewHeight=view.getLayoutParams().height;

ViewWidth=view.getLayoutParams().width;

Button btn_close=(Button) findViewById(R.id.btn_close);

Button btn_back=(Button) findViewById(R.id.btn_back);

btn_close.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

MyWindowManager.removeBigView(context);

MyWindowManager.removeSmallWindow(context);

Intent intent=new Intent(getContext(), WindowService.class);

context.stopService(intent);

}

});

btn_back.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

MyWindowManager.removeBigView(context);

MyWindowManager.createSmallWindow(context);

}

});

}

}

大悬浮窗的实体类 里面就是绑定刚才的大悬浮窗视图,并找到两个按钮,监听一个 关闭 和一个 返回的事件,  MyWindowManager将在下面创建

6,小悬浮窗的实体类

public class FloatSmallView extends LinearLayout {

public static int ViewHeight;

public static int ViewWidth;

//系统状态栏的高度

private static int statusHeight;

private WindowManager mWindowManager;

//小悬浮窗布局

private LinearLayout smallViewLayout;

//小火箭

private ImageView rocketImg;

//小悬浮窗参数

private WindowManager.LayoutParams mLayoutParams;

//记录手指在屏幕按下时的横坐标

private float xDown;

//记录手指在屏幕按下时的纵坐标

private float yDown;

//记录手指在屏幕移动时的横坐标

private float xMove;

//记录手指在屏幕移动时的纵坐标

private float yMove;

//记录手指按下时在小悬浮窗的横坐标

private float xInView;

//记录手指按下时在小悬浮窗的纵坐标

private float yInView;

//记录小火箭的高度

private int rocketHeight;

//记录小火箭的宽度

private int rocketWidth;

//记录当前手指是否在悬浮窗按下

private boolean isPressed;

public FloatSmallView(Context context) {

super(context);

mWindowManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

LayoutInflater.from(context).inflate(R.layout.small_view,this);

smallViewLayout=(LinearLayout) findViewById(R.id.ll_smallView);

ViewHeight=smallViewLayout.getLayoutParams().height;

ViewWidth=smallViewLayout.getLayoutParams().width;

rocketImg=(ImageView) findViewById(R.id.iv_recketImg);

rocketHeight=rocketImg.getLayoutParams().height;

rocketWidth=rocketImg.getLayoutParams().width;

TextView tv_percent=(TextView) findViewById(R.id.tv_percent);

tv_percent.setText(MyWindowManager.getUsedPercentValue(context));

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

isPressed = true;

// 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度

xInView = event.getX();

yInView = event.getY();

xDown = event.getRawX();

yDown= event.getRawY() - getStatusBarHeight();

xMove = event.getRawX();

yMove = event.getRawY() - getStatusBarHeight();

break;

case MotionEvent.ACTION_MOVE:

xMove=event.getRawX();

yMove=event.getRawY()-getStatusBarHeight();

updateViewStatus();

updateViewPosition();

break;

case MotionEvent.ACTION_UP:

isPressed=false;

if(MyWindowManager.isReadyToLuncher()){

luncherRocket();

}

else{

updateViewStatus();

if(xDown==xMove&&yDown==yMove){

Log.e("info","进入1");

openBigWindow();

}

}

break;

}

return true;

}

//打开大悬浮窗口,关闭小悬浮窗

private void openBigWindow(){

Log.e("info","进入2");

MyWindowManager.createBigView(getContext());

MyWindowManager.removeSmallWindow(getContext());

}

//开始发射小火箭

private void luncherRocket(){

MyWindowManager.removeRocketLuncher(getContext());

new LuncherTask().execute();

}

//传入小悬浮窗的参数, 用于更新位置

public void setParams(WindowManager.LayoutParams mParams){

this.mLayoutParams=mParams;

}

//更新小悬浮窗的位置

private void updateViewPosition(){

mLayoutParams.x=(int) (xMove-xInView);

mLayoutParams.y=(int) (yMove-yInView);

mWindowManager.updateViewLayout(this, mLayoutParams);

//检查小火箭是否到了发射台

MyWindowManager.updateLuncher();

}

//更新悬浮窗的显示样式  ,如果是按下状态 则显示为小火箭 否则为普通悬浮窗

private void updateViewStatus(){

if(isPressed&&rocketImg.getVisibility()!=View.VISIBLE){

mLayoutParams.width=rocketWidth;

mLayoutParams.height=rocketHeight;

mWindowManager.updateViewLayout(this, mLayoutParams);

smallViewLayout.setVisibility(View.GONE);

rocketImg.setVisibility(View.VISIBLE);

MyWindowManager.createLuncher(getContext());

}

else if(!isPressed){

mLayoutParams.width=ViewWidth;

mLayoutParams.height=ViewHeight;

mWindowManager.updateViewLayout(this, mLayoutParams);

smallViewLayout.setVisibility(View.VISIBLE);

rocketImg.setVisibility(View.GONE);

MyWindowManager.removeRocketLuncher(getContext());

}

}

//开始执行发射小火箭的任务

class LuncherTask extends AsyncTask<Void,Void, Void>{

@Override

protected Void doInBackground(Void... arg0) {

while(mLayoutParams.y>0){

mLayoutParams.y=mLayoutParams.y-20;

publishProgress();

try {

Thread.sleep(30);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

return null;

}

@Override

protected void onProgressUpdate(Void... values) {

mWindowManager.updateViewLayout(FloatSmallView.this, mLayoutParams);

}

@Override

protected void onPostExecute(Void result) {

//小火箭升空后 回归悬浮窗状态

updateViewStatus();

mLayoutParams.x=(int) (xDown-xInView);

mLayoutParams.y=(int) (yDown-yInView);

mWindowManager.updateViewLayout(FloatSmallView.this, mLayoutParams);

}

}

//获取状态栏的高度

private int getStatusBarHeight() {

if (statusHeight == 0) {

try {

Class<?> c = Class.forName("com.android.internal.R$dimen");

Object o = c.newInstance();

Field field = c.getField("status_bar_height");

int x = (Integer) field.get(o);

statusHeight = getResources().getDimensionPixelSize(x);

} catch (Exception e) {

e.printStackTrace();

}

}

return statusHeight;

}

}

小悬浮窗中方法较多,注释较多

7.创建发射台实体类RocketLuncher.java

//火箭发射台

public class RocketLuncher extends LinearLayout {

public static int width;

public static int height;

private ImageView luncherImg;

public RocketLuncher(Context context) {

super(context);

LayoutInflater.from(context).inflate(R.layout.luncher, this);

luncherImg=(ImageView) findViewById(R.id.iv_luncher);

width=luncherImg.getLayoutParams().width;

height=luncherImg.getLayoutParams().height;

}

//更新火箭发射台的显示状态

public void updateLuncherState(boolean isReadyToLuncher){

if(isReadyToLuncher){

luncherImg.setImageResource(R.drawable.launcher_bg_fire);

}

else{

luncherImg.setImageResource(R.drawable.launcher_bg_hold);

}

}

}

8,新建一个MyWindowManager.java用来管理这几个悬浮窗

public class MyWindowManager {

//小悬浮窗的实例

private static FloatSmallView mSmallView;

//大悬浮窗的实例

private static FloatBigView mBigView;

//火箭发射台的实例

private static RocketLuncher rocketLuncher;

//小悬浮窗的参数

private static LayoutParams mSmallViewParams;

//大悬浮窗的参数

private static LayoutParams mBigViewParams;

//火箭发射台的参数

private static LayoutParams rocketLuncherParams;

//用于在屏幕上添加或移除窗口

private static WindowManager mWindowManager;

//获取手机可用内存

private static ActivityManager mActivityManager;

//创建小悬浮窗

public static void createSmallWindow(Context context){

WindowManager windowManager=getWindowManager(context);

int screenWidth=windowManager.getDefaultDisplay().getWidth();

int screenHeight=windowManager.getDefaultDisplay().getHeight();

if(mSmallView==null){

mSmallView=new FloatSmallView(context);

if(mSmallViewParams==null){

mSmallViewParams=new LayoutParams();

mSmallViewParams.type=LayoutParams.TYPE_SYSTEM_ALERT;

mSmallViewParams.format=PixelFormat.RGBA_8888;

mSmallViewParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL

| LayoutParams.FLAG_NOT_FOCUSABLE;

mSmallViewParams.gravity=Gravity.LEFT|Gravity.TOP;

mSmallViewParams.width=FloatSmallView.ViewWidth;

mSmallViewParams.height=FloatSmallView.ViewHeight;

mSmallViewParams.x=screenWidth;

mSmallViewParams.y=screenHeight/2;

}

mSmallView.setParams(mSmallViewParams);

windowManager.addView(mSmallView, mSmallViewParams);

}

}

//将小悬浮窗从屏幕上移除

public static void removeSmallWindow(Context context){

if(mSmallView!=null){

WindowManager windowManager=getWindowManager(context);

windowManager.removeView(mSmallView);

mSmallView=null;

}

}

//创建大悬浮窗

public static void createBigView(Context context){

WindowManager windowManager=getWindowManager(context);

int screenWidth=windowManager.getDefaultDisplay().getWidth();

int screenHeight=windowManager.getDefaultDisplay().getHeight();

if(mBigView==null){

mBigView=new FloatBigView(context);

if(mBigViewParams==null){

mBigViewParams=new LayoutParams();

mBigViewParams.x=screenWidth/2-FloatBigView.ViewWidth/2;

mBigViewParams.y=screenHeight/2-FloatBigView.ViewHeight/2;

mBigViewParams.type=LayoutParams.TYPE_PHONE;

mBigViewParams.format= PixelFormat.RGBA_8888;

mBigViewParams.gravity=Gravity.LEFT|Gravity.TOP;

mBigViewParams.width=FloatBigView.ViewWidth;

mBigViewParams.height=FloatBigView.ViewHeight;

}

windowManager.addView(mBigView, mBigViewParams);

}

}

//将大悬浮窗移除

public static void removeBigView(Context context){

if(mBigView!=null){

WindowManager windowManager=getWindowManager(context);

windowManager.removeView(mBigView);

mBigView=null;

}

}

//创建一个火箭发射台

public static void createLuncher(Context context){

WindowManager windowManager=getWindowManager(context);

int screenWidht=windowManager.getDefaultDisplay().getWidth();

int screenHeight=windowManager.getDefaultDisplay().getHeight();

if(rocketLuncher==null){

rocketLuncher=new RocketLuncher(context);

if(rocketLuncherParams==null){

rocketLuncherParams=new LayoutParams();

rocketLuncherParams.x=screenWidht/2-RocketLuncher.width/2;

rocketLuncherParams.y=screenHeight-RocketLuncher.height;

rocketLuncherParams.type=LayoutParams.TYPE_PHONE;

rocketLuncherParams.format=PixelFormat.RGBA_8888;

rocketLuncherParams.gravity=Gravity.LEFT|Gravity.TOP;

rocketLuncherParams.width=RocketLuncher.width;

rocketLuncherParams.height=RocketLuncher.height;

}

windowManager.addView(rocketLuncher, rocketLuncherParams);

}

}

//移除火箭发射台

public static void removeRocketLuncher(Context context){

if(rocketLuncher!=null){

WindowManager wm=getWindowManager(context);

wm.removeView(rocketLuncher);

rocketLuncher=null;

}

}

//更新火箭发射台的显示状态

public static void updateLuncher(){

if(rocketLuncher!=null){

rocketLuncher.updateLuncherState(isReadyToLuncher());

}

}

//更新小悬浮窗TextView的内存占比

public static void updateUserPercent(Context context){

if(mSmallView!=null){

TextView percent=(TextView) mSmallView.findViewById(R.id.tv_percent);

percent.setText(getUsedPercentValue(context));

}

}

//是否有悬浮窗

public static boolean isWindowShow(){

return mSmallView!=null||mBigView!=null;

}

/**

* 计算已使用内存的百分比,并返回。

*

* @param context

*            可传入应用程序上下文。

* @return 已使用内存的百分比,以字符串形式返回。

*/

public static String getUsedPercentValue(Context context) {

String dir = "/proc/meminfo";

try {

FileReader fr = new FileReader(dir);

BufferedReader br = new BufferedReader(fr, 2048);

String memoryLine = br.readLine();

String subMemoryLine = memoryLine.substring(memoryLine

.indexOf("MemTotal:"));

br.close();

long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll(

"\\D+", ""));

long availableSize = getAvailableMemory(context) / 1024;

int percent = (int) ((totalMemorySize - availableSize)

/ (float) totalMemorySize * 100);

return percent + "%";

} catch (IOException e) {

e.printStackTrace();

}

return "悬浮窗";

}

/**

* 获取当前可用内存,返回数据以字节为单位。

*

* @param context

*            可传入应用程序上下文。

* @return 当前可用内存。

*/

private static long getAvailableMemory(Context context) {

ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();

getActivityManager(context).getMemoryInfo(mi);

return mi.availMem;

}

//判断小火箭是否准备好发射

public static boolean isReadyToLuncher(){

if ((mSmallViewParams.x > rocketLuncherParams.x && mSmallViewParams.x

+ mSmallViewParams.width < rocketLuncherParams.x

+ rocketLuncherParams.width)

&& (mSmallViewParams.y + mSmallViewParams.height > rocketLuncherParams.y)) {

return true;

}

return false;

}

//得到WindowManager的单例

private static WindowManager getWindowManager(Context context){

if(mWindowManager==null){

mWindowManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

}

return mWindowManager;

}

//得到ActivityManager的单例

private static ActivityManager getActivityManager(Context context){

if(mActivityManager==null){

mActivityManager=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

}

return mActivityManager;

}

}

9.悬浮窗的服务WindowService.java,用来时刻检查当前视图是否该显示悬浮窗还是隐藏.

public class WindowService extends Service {

//在线程中创建或移除悬浮窗

private Handler handler=new Handler();

//定时器 检查当前是应该创建还是移除悬浮窗

private Timer mTimer;

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

if(mTimer==null){

mTimer=new Timer();

mTimer.scheduleAtFixedRate(new RefreshTaks(), 0, 500);

}

return super.onStartCommand(intent, flags, startId);

}

@Override

public void onDestroy() {

super.onDestroy();

mTimer.cancel();

mTimer=null;

}

class RefreshTaks extends TimerTask{

@Override

public void run() {

//如果当前是桌面且没有窗口显示,则创建小悬浮窗

if(isHome()&&!MyWindowManager.isWindowShow()){

handler.post(new Runnable() {

@Override

public void run() {

MyWindowManager.createSmallWindow(getApplicationContext());

}

});

}

//如果不是桌面,且有悬浮窗显示,则移除悬浮窗

else if(!isHome()&&MyWindowManager.isWindowShow()){

handler.post(new Runnable() {

@Override

public void run() {

MyWindowManager.removeBigView(getApplicationContext());

MyWindowManager.removeSmallWindow(getApplicationContext());

}

});

}

//当前是桌面 且有悬浮窗显示  则更新内存

else if(isHome()&&MyWindowManager.isWindowShow()){

handler.post(new Runnable() {

@Override

public void run() {

MyWindowManager.updateUserPercent(getApplicationContext());

}

});

}

}

}

/**

* 判断当前界面是否是桌面

*/

private boolean isHome() {

ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);

return getHomes().contains(rti.get(0).topActivity.getPackageName());

}

/**

* 获得属于桌面的应用的应用包名称

*

* @return 返回包含所有包名的字符串列表

*/

private List<String> getHomes() {

List<String> names = new ArrayList<String>();

PackageManager packageManager = this.getPackageManager();

Intent intent = new Intent(Intent.ACTION_MAIN);

intent.addCategory(Intent.CATEGORY_HOME);

List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,

PackageManager.MATCH_DEFAULT_ONLY);

for (ResolveInfo ri : resolveInfo) {

names.add(ri.activityInfo.packageName);

}

return names;

}

@Override

public IBinder onBind(Intent arg0) {

return null;

}

}

10.打开MainActivity.java

public class MainActivity extends ActionBarActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button btn_start=(Button) findViewById(R.id.btn_start);

btn_start.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Intent intent=new Intent(MainActivity.this, WindowService.class);

MainActivity.this.startService(intent);

MainActivity.this.finish();

}

});

}

}

开启服务.

来自为知笔记(Wiz)

时间: 2024-10-25 22:35:45

android桌面悬浮窗仿QQ手机管家加速效果的相关文章

Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8689140 大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多高手喜欢把自己的经验写在网上,供大家来学习,我也是从中受惠了很多,在此我深表感谢.可是我发现我却从来没有将自己平时的一些心得拿出来与大家分享,共同学习,太没有奉献精神了.

Android -- 桌面悬浮,仿360

实现原理                                                                               这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多.主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除悬浮窗.其中悬浮窗的参数有必要详细说明一下. WindowManager

自制window下core animation引擎 - demo第二弹 - 仿QQ电脑管家加速小火箭

一年前想写一个像cocoa那样,可以方便层动画开发的引擎,写着写着又逆向它的QuartzCore.framework,也就是CoreAnimation的底层,已经大半年没有搞windows这个引擎.大体来看,动画简单来说有9要素,矩形区域(x, y, w, h),仿射变换矩阵(translation, rotation, scale),还有就是透明度alpha,除此还必须有线性变化函数.这些在cocoa中构成了最基本的动画,也最常用,通常提交动画一个始态,一个终态,以及时间就OK了.有次序的动画

android桌面悬浮窗实现

                        首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. 1.新建一个项目 , 打开activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.an

Android桌面悬浮窗

经常,我们看到在桌面上可移动的悬浮窗,这种场景还是很多的, 像流量统计,桌面歌词等,安全软件的清理小部件 这种小部件主要是通过 WindowManager ; WindowManager.LayoutParams 这两个类来实现 调用 WindowManager 的addView(view, params)方法来添加一个悬浮窗.updateViewLayout(view,params)来更新悬浮窗参数.removeView(view)用于移除悬浮窗 WindowManager.LayoutPar

仿QQ电脑管家圆形效果

刚要睡觉,猛然扫到了QQ电脑管家的这个东西.... 心理痒痒的...没办法,只能做出来再去睡了 <!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <style> #box{ position:relative; margin:200px auto; width:220px; height:220px; bo

Android自定义View实现仿QQ实现运动步数效果

效果图: 1.attrs.xml中 <declare-styleable name="QQStepView"> <attr name="outerColor" format="color"/> <attr name="innerColor" format="color"/> <attr name="borderWidth" format=&quo

Android -- 桌面悬浮,QQ管家火箭实现

续上一篇博客<Android -- 桌面悬浮,仿360>,传送门:http://www.cnblogs.com/yydcdut/p/3909888.html,在此代码上继续添加实现. 比起普通的桌面悬浮窗,现在我们需要在拖动悬浮窗的时候将悬浮窗变成一个小火箭,并且在屏幕的底部添加一个火箭发射台.那么我们就从火箭发射台开始编写吧,首先创建launcher.xml作为火箭发射台的布局文件: <?xml version="1.0" encoding="UTF-8&

android 仿QQ手机版

千人2群开启,欢迎大家围观打酱油,群号145667827 您当前位置 : JavaApk-安卓应用游戏源码服务专家 » QQ » Android项目源码界面超级华丽的仿QQ最新版本 Android项目源码界面超级华丽的仿QQ最新版本 05 2014.05 作者:JavaApk   发布:2014-05-05 12:40   字符数:222   分类:QQ, VIP源码, 即时聊天   阅读: 2,392 次   18条评论 本项目是一个高仿QQ最新版本的项目,界面超级华丽,使用了大量的自定义控件