墨迹天气php,Android_仿墨迹天气在Android App中实现自定义zip皮肤更换,在这里谈一下墨迹天气的换肤 - phpStudy...

本文详细介绍了如何仿照墨迹天气在Android应用中实现ZIP格式的皮肤更换功能。通过解压下载的ZIP皮肤包到应用内部目录,提高加载速度和安全性。在用户选择皮肤后,将ZIP包内容解压缩到特定路径,然后读取这些资源来替换原有界面背景。文章还提到了使用ant.jar工具进行文件操作,并提供了部分关键代码示例。
摘要由CSDN通过智能技术生成

仿墨迹天气在Android App中实现自定义zip皮肤更换

在这里谈一下墨迹天气的换肤实现方式,不过首先声明我只是通过反编译以及参考了一些网上其他资料的方式推测出的换肤原理, 在这里只供参考. 若大家有更好的方式, 欢迎交流.

墨迹天气下载的皮肤就是一个zip格式的压缩包,在应用的时候把皮肤资源释放到墨迹天气应用的目录下,更换皮肤时新的皮肤资源会替换掉老的皮肤资源每次加载的时候就是从手机硬盘上读取图片,这些图片资源的命名和程序中的资源的命名保持一致,一旦找不到这些资源,可以选择到系统默认中查找。这种实现是直接读取了外部资源文件,在程序运行时通过代码显示的替换界面的背景资源。这种方式的优点是:皮肤资源的格式定义很随意可以是zip也可以是自定义的格式,只要程序中能够解析到资源就行,缺点是效率上的问题.

这里需要注意的一点是,再这里对压缩包的解压,借助了第三方工具: ant. jar进行解压和压缩文件. 关于ant工具的使用,我在稍后的文章中会具体介绍.

主要技术点:

如何去读取zip文件中的资源以及皮肤文件存放方式

实现方案:如果软件每次启动都去读取SD卡上的皮肤文件,速度会比较慢。较好的做法是提供一个皮肤设置的界面,用户选择了哪一个皮肤,就把那个皮肤文件解压缩到”/data/data/[package name]/skin”路径下(读取的快速及安全性),这样不需要跨存储器读取,速度较快,而且不需要每次都去zip压缩包中读取,不依赖SD卡中的文件,即使皮肤压缩包文件被删除了也没有关系。

实现方法:

1. 在软件的帮助或者官网的帮助中提示用户将皮肤文件拷贝到SD卡指定路径下。

2. 在软件中提供皮肤设置界面。可以在菜单或者在设置中。可参考墨迹、搜狗输入法、QQ等支持换肤的软件。

3. 加载指定路径下的皮肤文件,读取其中的缩略图,在皮肤设置界面中显示,将用户选中的皮肤文件解压缩到”/data/data/[package name]/skin”路径下。

4. 软件中优先读取”/data/data/[package name]/skin/”路径下的资源。如果没有则使用apk中的资源。

效果图:

具体代码:

1. AndroidManifest.xml:

package="com.tony.skin" android:versionCode="1" android:versionName="1.0">

android:label="@string/app_name">

2.布局文件main.xml

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="#d2d2d2"

android:id="@+id/layout">

android:text="请先点击“导入皮肤”,会将/sdcard/skin.zip导入到/sdcard/Skin_kris目录下,然后点击‘换肤'会将sdcard里面的素材用作皮肤"

android:textColor="#000">

3. Re_Skin2Activity:

package com.tony.skin;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.drawable.BitmapDrawable;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.Toast;

import com.tony.skin.utils.ZipUtil;

/**

*

* @author Tony

*

*/

public class Re_Skin2Activity extends Activity implements OnClickListener{

private Button btnSet;

private Button btnImport;

private LinearLayout layout;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btnSet = (Button)findViewById(R.id.button1);

btnSet.setOnClickListener(this);

btnImport = (Button)findViewById(R.id.button2);

btnImport.setOnClickListener(this);

layout = (LinearLayout)findViewById(R.id.layout);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.button1:

Bitmap bitmap= BitmapFactory.decodeFile("/sdcard/tony/skin/skin.png");

BitmapDrawable bd=new BitmapDrawable(bitmap);

btnSet.setBackgroundDrawable(bd);

layout.setBackgroundDrawable(new BitmapDrawable(BitmapFactory.decodeFile("/sdcard/Skin_kris/skin/bg/bg.png")));

break;

case R.id.button2:

ZipUtil zipp = new ZipUtil(2049);

System.out.println("begin do zip");

zipp.unZip("/sdcard/skin.zip","/sdcard/Skin_kris");

Toast.makeText(this, "导入成功", Toast.LENGTH_SHORT).show();

break;

default:

break;

}

}

}

4. ZipUtil 解压缩处理ZIP包的工具类

package com.tony.skin.utils;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.Enumeration;

import java.util.zip.Deflater;

import org.apache.tools.zip.ZipEntry;

import org.apache.tools.zip.ZipFile;

import org.apache.tools.zip.ZipOutputStream;

/**

* Zip包压缩,解压处理工具类

* @author a

*

*/

public class ZipUtil {

private ZipFile zipFile;

private ZipOutputStream zipOut; //压缩Zip

private int bufSize; //size of bytes

private byte[] buf;

private int readedBytes;

public ZipUtil(){

this(512);

}

public ZipUtil(int bufSize){

this.bufSize = bufSize;

this.buf = new byte[this.bufSize];

}

/**

*

* @param srcFile 需要 压缩的目录或者文件

* @param destFile 压缩文件的路径

*/

public void doZip(String srcFile, String destFile) {// zipDirectoryPath:需要压缩的文件夹名

File zipDir;

String dirName;

zipDir = new File(srcFile);

dirName = zipDir.getName();

try {

this.zipOut = new ZipOutputStream(new BufferedOutputStream(

new FileOutputStream(destFile)));

//设置压缩的注释

zipOut.setComment("comment");

//设置压缩的编码,如果要压缩的路径中有中文,就用下面的编码

zipOut.setEncoding("GBK");

//启用压缩

zipOut.setMethod(ZipOutputStream.DEFLATED);

//压缩级别为最强压缩,但时间要花得多一点

zipOut.setLevel(Deflater.BEST_COMPRESSION);

handleDir(zipDir, this.zipOut,dirName);

this.zipOut.close();

} catch (IOException ioe) {

ioe.printStackTrace();

}

}

/**

* 由doZip调用,递归完成目录文件读取

* @param dir

* @param zipOut

* @param dirName 这个主要是用来记录压缩文件的一个目录层次结构的

* @throws IOException

*/

private void handleDir(File dir, ZipOutputStream zipOut,String dirName) throws IOException {

System.out.println("遍历目录:"+dir.getName());

FileInputStream fileIn;

File[] files;

files = dir.listFiles();

if (files.length == 0) {// 如果目录为空,则单独创建之.

// ZipEntry的isDirectory()方法中,目录以"/"结尾.

System.out.println("压缩的 Name:"+dirName);

this.zipOut.putNextEntry(new ZipEntry(dirName));

this.zipOut.closeEntry();

} else {// 如果目录不为空,则分别处理目录和文件.

for (File fileName : files) {

// System.out.println(fileName);

if (fileName.isDirectory()) {

handleDir(fileName, this.zipOut,dirName+File.separator+fileName.getName()+File.separator);

} else {

System.out.println("压缩的 Name:"+dirName + File.separator+fileName.getName());

fileIn = new FileInputStream(fileName);

this.zipOut.putNextEntry(new ZipEntry(dirName + File.separator+fileName.getName()));

while ((this.readedBytes = fileIn.read(this.buf)) > 0) {

this.zipOut.write(this.buf, 0, this.readedBytes);

}

this.zipOut.closeEntry();

}

}

}

}

/**

* 解压指定zip文件

* @param unZipfile 压缩文件的路径

* @param destFile   解压到的目录

*/

public void unZip(String unZipfile, String destFile) {// unZipfileName需要解压的zip文件名

FileOutputStream fileOut;

File file;

InputStream inputStream;

try {

this.zipFile = new ZipFile(unZipfile);

for (Enumeration entries = this.zipFile.getEntries(); entries

.hasMoreElements();) {

ZipEntry entry = (ZipEntry) entries.nextElement();

file = new File(destFile+File.separator+entry.getName());

if (entry.isDirectory()) {

file.mkdirs();

} else {

// 如果指定文件的目录不存在,则创建之.

File parent = file.getParentFile();

if (!parent.exists()) {

parent.mkdirs();

}

inputStream = zipFile.getInputStream(entry);

fileOut = new FileOutputStream(file);

while ((this.readedBytes = inputStream.read(this.buf)) > 0) {

fileOut.write(this.buf, 0, this.readedBytes);

}

fileOut.close();

inputStream.close();

}

}

this.zipFile.close();

} catch (IOException ioe) {

ioe.printStackTrace();

}

}

// 设置缓冲区大小

public void setBufSize(int bufSize) {

this.bufSize = bufSize;

}

}

相关阅读:

自己实现ajax封装示例分享

快速解决Android平台移植ffmpeg的一些问题

JavaScript中的条件判断语句使用详解

linux下apache、mysql、php安装配置详细笔记

iOS下PDF文件的浏览和涂鸦效果的简单实现

Ubuntu系统怎么手动进行更新升级?

php中autoload的用法总结

JavaScript实现跨浏览器的添加及删除事件绑定函数实例

JS鼠标滑过图片时切换图片实现思路

php 实现进制相互转换

Windows10如何连接到工作区以便对电脑进行管理

JS对象与json字符串格式转换实例

win10不能启动apache该怎么解决?

win10下迅雷看看播放器如何彻底取消开机自启?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值