每逢重大节日,App icon 就要跟一波“潮流”做一次更换,节日过后再换回普通。如何保证这两次切换流程丝滑顺畅呢?

应用内需要更换的 icon 包括两处,一个是 App 主 icon,默认放在 xcassets 里面,另一个就是 App 内部页面所使用的 icon。

App 主 icon 更换

苹果这边需要的 icon 实在太多了,如果像我们 App 一样支持 iPad 那么大大小小的 icon 就需要 18 张,就算让设计师同学给到所有需要的尺寸我们自己在 .xcassets 一一对应起来也是超级麻烦,如果我们只需要提供一张高清图(1024x1024 pixel)剩下的能通过工具自动对应起来该多好啊!

研究xcassets结构后发现,AppIcon 类型的图片是一个后缀名为 appiconset 的文件夹,该文件夹里面除了有 APP 需要的各种尺寸的 png 图片外,还有一个 Contents.json 文件,形如:

{
  "images" : [
    {
      "size" : "20x20",
      "idiom" : "iphone",
      "filename" : "IOS_40-2.png",
      "scale" : "2x"
    },
    {
      "size" : "83.5x83.5",
      "idiom" : "ipad",
      "filename" : "IOS_167.png",
      "scale" : "2x"
    },
    {
      "size" : "1024x1024",
      "idiom" : "ios-marketing",
      "filename" : "IOS_1024.png",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

描述了了各种尺寸的图片如何与文件夹中的 png 图片对应,我们按照此规律便可以写一个更换 AppIcon 的工具。

之前确实听说过有自动生成这种 icon 的工具 App 但我没有使用过,要为如此一个小功能下载一个 App 我觉得太不环保了。还是自己写一个脚本实现比较低碳。下面是 python 程序和注释

# !/usr/local/bin/python3
# _*_ coding:utf-8 _*_

__doc__="""
    输入:一个 1024*1024 的 png 图片
    输出: AppIconxxxxx.appiconset 目录,包含 iPhone 和 iPad 所需的 App Icons
"""

import os,sys
import imghdr
import json
import random,shutil

from PIL import Image,ImageFile

class FileSet:
    def __init__(self,filename,scale):
        self.filename = filename
        self.scale = scale

    @classmethod
    def fileset(cls,scale,size,prefix):
        filename = "{}.{}.{}.png".format(size,scale,prefix)
        file_set = FileSet(filename,scale)
        return file_set

class ImageSet:
    def __init__(self,size,idiom,filesets):
        self.size = size    # 单边
        self.idiom = idiom
        self.filesets = filesets    # 数组,包含文件名,一个 size 可能有多个 scale,所有会有多个文件 set
    def json_desc(self):
        descs = []
        for fileset in self.filesets:
            json_dict = {"size":"{}x{}".format(self.size,self.size),
                        "idiom":self.idiom,
                        "filename":fileset.filename,
                        "scale":"{}x".format(fileset.scale)}
            descs.append(json_dict)
        return descs

    @classmethod
    def iPhone_set(cls,size,filesets):
        return ImageSet(size,'iphone',filesets)
    @classmethod
    def iPad_set(cls,size,filesets):
        return ImageSet(size,'ipad',filesets)

    @classmethod
    def market_set(cls,file_prefix=''):
        size = 1024
        return ImageSet(size,idiom='ios-marketing',filesets=[FileSet.fileset(1,size,file_prefix)])

def get_img_sets(iPad=False,iPhone=False,file_prefix=''):
    img_sets = []
    if iPad:
        for size in [20,29,40,76]:
            file_sets = [FileSet.fileset(2,size,file_prefix),FileSet.fileset(1,size,file_prefix)]
            one_set = ImageSet.iPad_set(size,file_sets)
            img_sets.append(one_set)
        img_sets.append(ImageSet.iPad_set(83.5,[FileSet.fileset(2,83.5,file_prefix)]))
    if iPhone:
        for size in [20,29,40,60]:
            file_sets = [FileSet.fileset(2,size,file_prefix),FileSet.fileset(3,size,file_prefix)]
            one_set = ImageSet.iPhone_set(size,file_sets)
            img_sets.append(one_set)
    img_sets.append(ImageSet.market_set(file_prefix))
    return img_sets

def create_appicon_set(imgobj,t_path='',iPad=False,iPhone=True):
    rand_str = str(random.randint(20000,2147483648))
    t_folder_path = os.path.join(t_path,"AppIcon"+ rand_str +".appiconset")
    os.makedirs(t_folder_path)
    img_sets = get_img_sets(iPad=iPad,iPhone=iPhone,file_prefix=rand_str)
    contents = {"info":{"version":1,"author":"xcode"}}
    images = []
    for single_set in img_sets:
        for fileset in single_set.filesets:
            scale_size = (int(single_set.size * fileset.scale), int(single_set.size * fileset.scale))
            img_obj = imgobj.resize(scale_size,Image.ANTIALIAS)
            real_path = os.path.join(t_folder_path,fileset.filename)
            img_obj.save(real_path)
            print("保存文件{},\t路径:{}".format(scale_size,real_path))
        images += single_set.json_desc()
    contents["images"] = images
    with open(os.path.join(t_folder_path,"Contents.json"),"w") as wf:
        wf.write(json.dumps(contents,indent=4))

if __name__ == '__main__':

    argvs = sys.argv[1:] if len(sys.argv) == 3 else None
    if not argvs:
        print("Fatal: 要求两个参数,第一个是图片路径,第二个是目标目录")
        sys.exit(-1)

    o_img_path,t_path = argvs

    if not os.path.isfile(o_img_path) or not imghdr.what(o_img_path) in ['png']:
        print("Fatal: 图片路径不存在或者非 png 格式图片")
        sys.exit(-1)

    if not os.path.isdir(t_path):
        print("Fatal: 目标路径不存在或者非目录")
        sys.exit(-1)

    o_img = Image.open(o_img_path)
    if (1024,1024) != o_img.size :
        print("Fatal: 图片非 1024x1024 pixel 尺寸")
        sys.exit(-1)
"""
碰到设计师犯糊,将肉眼看不见但确实带有 Alpha 通道的图片提供给我们,直到我们在提交 App Store 的那一刻苹果报错说带有 Alpha 通道,然后我们又要重新走一遍流程												

如何更换 App icon的更多相关文章

  1. 【转】【iOS】动态更换App图标

    原文网址:http://www.cocoachina.com/ios/20170619/19557.html 前言 动态更换App图标这件事,在用户里总是存在需求的:有些用户喜欢“美化”自己的手机.至 ...

  2. 在设置app icon时的问题

    APP 运行时遇到 the app icon set named appicon did not have any applicable content 是应该考虑是icon可能偏大

  3. [摘抄]iOS App icon、启动页、图标规范

    以下内容都是我在做App时通过自己的经验和精品的分析得来的,希望会帮助到你.但是有时个别情况也要个别分析,要活学活用. 一. App  Icon 在设计iOS App Icon时,设计师不需要切圆角, ...

  4. [iOS]The app icon set named "AppIcon" did not have any applicable content.

    Develop Tools: xCode 5.1 I write a demo for app settings feature. The tutorial url is here. When I a ...

  5. App Icon生成工具(转载)

    原地址:http://www.cocoachina.com/bbs/read.php?tid=290247 下载软件:在AppStore搜索App Icon Gear 打开软件 决定制作启动图或图标, ...

  6. 【初级为题,大神绕道】The app icon set named "AppIcon" did not have any applicable content 错误#解决方案#

    The app icon set named "AppIcon" did not have any applicable content 错误,怎样解决   按照您的错误提示您应该 ...

  7. mac app icon 设置

    mac app icon 设置 1:目前 mac app 所需要的icon 图标尺寸 icon_16x16.png 16px icon_16x16@2x.png 32px icon_32x32.png ...

  8. iOS App Icon图标 尺寸规范

    Commit to AppStore:1024*1024 //for App IconIcon-60@3x.png:180*180 //iPhone 6 Plus (@3x)Icon-60@2x.pn ...

  9. The app icon set named "AppIcon" did not have any applicable content.

    Develop Tools: xCode 5.1 I write a demo for app settings feature. The tutorial url is here. When I a ...

随机推荐

  1. Python一键转Jar包,Java调用Python新姿势!

    粉丝朋友们,不知道大家看故事看腻了没(要是没腻可一定留言告诉我^_^),今天这篇文章换换口味,正经的来写写技术文.言归正传,咱们开始吧! 本文结构: 需求背景 进击的Python Java和Pytho ...

  2. 什么是data:image/png;base64,?一道关于Data URI Scheme的入门级CTF_Web题

    一道关于Data URI Scheme的入门级CTF_Web题 0x00 题目描述 这是偶尔遇到的某网安交流群的入群题,题目没有任何的提示,直接给了一个txt文件. 0x01 解题过程 通过给的这个文 ...

  3. Numpy之数据保存与读取

      在pandas使用的25个技巧中介绍了几个常用的Pandas的使用技巧,不少技巧在机器学习和深度学习方面很有用处.本文将会介绍Numpy在数据保存和读取方面的内容,这些在机器学习和深度学习方向也大 ...

  4. python 异步请求

    这是循环请求10次页面.总时间大概是10秒左右,如果是普通的循环请求10次页面而不添加异步的话,时间大概在30秒以上,当然这个数据可能有误,因为有网速的问题存在,但大体的效果应该是不变的. impor ...

  5. kafka集群搭建及结合springboot使用

    1.场景描述 因kafka以前用的不多,只往topic中写入和读取过数据,这次刚好又要用到,记录下kafka集群搭建及结合springboot使用. 2. 解决方案 2.1 简单介绍 (一)关于kaf ...

  6. vs2017打包exe安装包

    1,安装扩展程序Install Projects 2,在打开的界面搜索Install,找到Install Projects 3,在要打包的项目解决方案下创建一个生成exe的项目 4,在打包项目的文件系 ...

  7. BeanShell断言:根据响应的2个数据的比较结果来决定断言

    需求:目前有一个请求,请求的响应中有2个值,aaa和bbb,我们比较aaa和bbb,如果aaa大于bbb,则断言通过,否则失败. 1.添加一个Dummy Sampler,模拟请求. 2.添加2个正则表 ...

  8. 云CRM和本地CRM哪个更好

    现在CRM系统按照服务器部署方式的不同分为本地CRM和云CRM两种,本地CRM需要在企业内部部署服务器,而云CRM的服务器则是安装在云服务器上面,很多企业可能不知道应该选择云CRM还是本地CRM.下面 ...

  9. Swift 4.0 中的错误处理及抛出错误

    在Swift的标准库,很多方法名后都带有'throws'这个关键词, 'throws'表示该方法在执行过程中遇到错误则抛出,但不会crash. 下面是Swift标准库中的一个构造方法,String.D ...

  10. javaWeb_Css

    CSS HTML页面实在太丑了,怎么破?! 第1章 CSS简介 CSS全称为“层叠样式表 (Cascading Style Sheets)”,它主要是用于定义HTML元素(或内容)在浏览器内的显示样式 ...