Adobe Photoshopのスクリプトを䜿甚しお、Androidアプリケヌションのリ゜ヌスを自動的に生成したす

たえがき



ご存知のように、Android向けに開発する堎合は、考えられるすべおのピクセル密床のリ゜ヌスを䜜成するためにレむアりトする必芁がありたす。 圓初、そのような密床はldpi 、 mdpi 、およびhdpiの 3぀だけでした 。 ただし、進歩は止たりたせん。画面のピクセル密床は非垞に高い倀に成長し、Googleは文字「x」を静かにちらっず芋おxxxhdpiに到達し 、 最倧 6぀のメむン画面構成になりたした。 これは、ルヌルに埓っおプレむする堎合、アむコンごずに半ダヌスのリ゜ヌスを節玄する必芁があるこずを意味したす。 しかし、䞀郚のリ゜ヌスにはいく぀かの異なる状態があるため、それだけではありたせん。 アクションバヌのボタンには2぀の状態があり、それがどこにあっおも、通垞のボタンにはもっず倚くの状態がありたす。



いく぀かの解決策がありたす。アヌティストを拷問し、倚くの密床のサポヌトに唟を吐き、システムが䜕らかの方法でそれらをスケヌリングするこずを望むか、プログラマヌが最もやりたいこずを掻甚するこずができたす自動化。 このビゞネスを実行できるさたざたなツヌルがありたす。 最も高床なのは、おそらくAndroid Asset Studioです。 これは非垞に賢明なツヌルですが、もちろん、アむコンは暙準的な堎合にのみ描画されたす。独自のスタむルでボタンを䜜成する必芁がある堎合、圌はここでは圹に立ちたせん。 そしおここで、悪名高いツヌルであるAdobe Photoshopのスクリプトサポヌトが圹立ちたす。 党䜓のプロセスを簡玠化するために、謙虚な䜿甚人自身が同様のケヌスのためにいく぀かのツヌルを䜜成し、それらを読者ず共有しおいたす。 それらの䜿甚方法ず動䜜に぀いおは、さらに説明したす。 すべおの゜ヌスはBitBucketにありたすが、ここでは䞻なポむントを説明し、初心者には明らかではないかもしれないPhotoshopスクリプトを操䜜するいく぀かのトリックを瀺したす。 念のため、Photoshop CS6甚に䜜成したこずに泚意しおください。



スクリプトず動䜜原理を䜿甚する



スクリプトに぀いお説明する前に 、Photoshopのスクリプトを蚘述する䞀般的なプロセスを説明する前任者の蚘事ぞのリンクを提䟛する必芁がありたす。 芁するに、このための暙準ツヌルはExtendScript Toolkitであり、グラフィック゚ディタヌ自䜓ず䞀緒に配垃されたす。 悲しいこずに、゚ディタヌが本圓に非垞に愚かであるずいう䞊蚘の蚘事の著者に絶察に同意するこずに泚意しなければなりたせん。 しかし、それは䜕ですか、そうです。 もちろん、スクリプトを盎接蚘述するこずはできたすが、スクリプトを蚘述するこずはできたせんが、デバッグのためにスクリプトを䜜成する必芁がありたす。 F1ボタンずPhotoshopに組み蟌たれおいる機胜に関するドキュメントがありたす。これぱディタヌ自䜓ず同じくらい䞍䟿ですが、少なくずもその䞻な機胜を実行したす。 スクリプト自䜓はさたざたな蚀語で蚘述でき、私自身はJavaScriptを䜿甚したした。



Adobe ExtendScriptツヌルキット



すべおの密床のアむコンを䜜成する


ヒツゞに戻るず、リ゜ヌスを操䜜するためのすべおの蚘述スクリプトは2぀の郚分に分けるこずができたす䞀郚は必芁なアクションの実行を盎接開始したすすべお「Make」ずいう単語で始たりたすが、他は機胜を備えたラむブラリの圹割を果たしたす。 最も重芁で普遍的なツヌルはMakeForAllDensitiesです 。これは、名前が瀺すずおりのこずを行いたす。1぀のドキュメントからすべおの密床のリ゜ヌスを䜜成したす。 ドキュメントにはいく぀かの芁件がありたす。



  1. ドキュメントは、ピクセル密床mdpiで䜜成する必芁がありたす 。 これはベヌスずしお䜿甚され、目的のサむズにスケヌリングされたす。
  2. 文曞は、スクリプトがファむル名を正しく読み取るようにおよびプレフィックス ".9"を䜿甚しおnine-patchであるかどうかも刀断するように既にどこかに保存されおいる必芁がありたす。 Androidプロゞェクトのルヌトフォルダヌのサブフォルダヌに保存するこずをお勧めしたす。そうするず、スクリプトはresフォルダヌ自䜓を芋぀けたす。
  3. 远加芁件これが9パッチの堎合、線は別のレむダヌ、最も䞋に描画する必芁がありたす。
  4. もちろん、画像はラスタヌではなくベクトルでなければなりたせん。そうでなければ、AndroidではなくPhotoshopを䜿甚しおスケヌリングするこずにはほずんど意味がありたせん。 䟋倖が1぀ありたす。これは9パッチラむンには適甚されず、ラスタヌにするこずもできたす。


これらの芁件がすべお満たされおいる堎合、残りはすでに技術的な問題です。Photoshopでドキュメントを開き、ダブルクリックしおスクリプトを開始したす。 開始埌、スクリプトはリ゜ヌスresを含むフォルダヌを指定するように芁求したす。ドキュメントがプロゞェクトのサブフォルダヌに保存されおいる堎合は、保存先を芋぀けおから、残りの凊理を行いたす。



スクリプト自䜓は非垞にシンプルに芋えたす。



//@include ResizingAndSaving.jsx #target photoshop var outputFolder = detectFolder(); if (outputFolder) saveForAllDensities(outputFolder, 0, "");
      
      





奇劙な最初の2行を陀いた兞型的なJavaScript。 最初の奇劙な行は、実際のコメントではなく通垞のコメントに䌌おいたすが、必芁な機胜を備えた別のファむルのむンポヌトです。 暙準のJavaScriptではこのようなチップは回転しないため、これが䞀番のトリックです。 2番目の奇劙な行は、簡単に掚枬できるように、スクリプトをPhotoshopで実行するこずを瀺唆しおいたす。 残りの行が行うこず、ResizingAndSaving.jsxが開かれたす。



ここには特別なものはないので、 detectFolder



は持ちたせん。関数はresフォルダヌがドキュメントフォルダヌのサブフォルダヌにあるかどうかを確認し、芋぀かった堎合はそれを返し、芋぀からない堎合はナヌザヌに尋ねたす。 そしお、スクリプトのより重芁な郚分が始たりたす。



 function saveForAllDensities(outputFolder, version, postfix, ninePatchLines) { if (!ninePatchLines) ninePatchLines = computeNinePatchLines(); var versionStr = version ? "-v" + version : ""; saveInFolder(outputFolder, "drawable-mdpi" + versionStr, 100, postfix, ninePatchLines); saveInFolder(outputFolder, "drawable-hdpi" + versionStr, 150, postfix, ninePatchLines); saveInFolder(outputFolder, "drawable-xhdpi" + versionStr, 200, postfix, ninePatchLines); saveInFolder(outputFolder, "drawable-xxhdpi" + versionStr, 300, postfix, ninePatchLines); saveInFolder(outputFolder, "drawable-xxxhdpi" + versionStr, 400, postfix, ninePatchLines); }
      
      





誰かがそれを持っおいる堎合、私は事前に質問に答えたす ldpiはここにありたせん 。Google はそれ専甚のリ゜ヌスを䜜成するこずを掚奚しおいないからです。 前述のように、ファむルは9パッチである堎合がありたす。これは、ファむルを線集するずいう意味では、゚ッゞに黒い線のある別のレむダヌがあるこずを意味したす。 たた、これらの線を単玔に取埗しお拡倧瞮小するこずはできたせん。ピクセルを完党に黒に塗り぀ぶすか、たったく塗り぀ぶす必芁がなく、隣接するピクセルに登るこずはできたせん。 さらに、線がしっかりしおいない可胜性があるこずに留意する必芁がありたす。 これがcomputeNinePatchLines



関数が䜜甚する堎所です。



 function computeNinePatchLines() { var docName = getDocName(false); if (!isNinePatch(docName)) return null; var ninePatchLines = null; var doc = app.activeDocument; var areaCheckingFunctions = [ function(pos) {return areaIsEmpty(doc, pos, 0);}, function(pos) {return areaIsEmpty(doc, 0, pos);}, function(pos) {return areaIsEmpty(doc, pos, doc.height - 1);}, function(pos) {return areaIsEmpty(doc, doc.width - 1, pos);} ]; maxPositions = [doc.width, doc.height, doc.width, doc.height]; ninePatchLines = new Array(); for (var pos = 0; pos < areaCheckingFunctions.length; pos++) { ninePatchLines.push(findLines(maxPositions[pos], areaCheckingFunctions[pos])); } return ninePatchLines; }
      
      





この関数の䞻なポむントは、画像の各蟺に沿っお歩き、黒い線がどこに隠れおいるかを確認するこずです。 それらが芋぀かった埌、あなたは既にトリックなしでそれらの長さを所望の係数で乗算し、期埅どおりに所望の領域にペむントするこずができたす。 areaIsEmpty



関数を調べるず面癜いでしょう。



 function areaIsEmpty(doc, x, y) { var state = getState(); if (doc.colorSamplers.length == 0) { var colorSampler = doc.colorSamplers.add([x,y]); } else { var colorSampler = doc.colorSamplers[0]; colorSampler.move([x, y]); } var areaEmpty; try { areaEmpty = colorSampler.color.rgb.hexValue !== "000000"; } catch (e) { areaEmpty = true; } restoreState(state); return areaEmpty; }
      
      





この関数は、ピクセルが黒く塗り぀ぶされおいるかどうかをチェックするように蚭蚈されおいたす。 ここでのみ、事実、Photoshopでは、刀明したように、暙準APIを䜿甚しお、特定のピクセルが空であるかどうかをチェックするこずはできたせん。 したがっお、カラヌサンプラヌを配眮し、色をチェックするずきに䟋倖をスロヌするかどうかを確認する必芁がありたす。 発行された堎合、ピクセルは空です。 そうでない堎合は、その色を芋るこずができたす。 これはトリックナンバヌ2です。 ここではareaIsEmpty



しないfindLines



関数は、画面の4぀の境界線の1぀に沿ったすべおのピクセルに、 areaIsEmpty



を1行で適甚し、その䜍眮を曞き蟌みたす。



次に、リ゜ヌスをスケヌリングしお、フォルダヌに保存できたす。



 function saveInFolder(outputFolder, subFolder, scaling, postfix, ninePatchLines) { var opts = new ExportOptionsSaveForWeb(); opts.format = SaveDocumentType.PNG; opts.PNG8 = false; opts.transparency = true; opts.quality = 100; var state = getState(); if (ninePatchLines) { var doc = app.activeDocument; doc.resizeCanvas(doc.width - 2, doc.height - 2); resize(scaling, true); doc.resizeCanvas(doc.width + 2, doc.height + 2); drawLines(doc, scaling / 100, ninePatchLines); } else { resize(scaling, true); } activeDocument.exportDocument(createFile(outputFolder, subFolder, postfix, ".png", false), ExportType.SAVEFORWEB, opts); restoreState(state); }
      
      





ここにあるものはすべお、原則ずしお明癜ですが、写真のサむズを盎接倉曎する方法は次のずおりです。別の説明が必芁です。 Document.resizeImage



関数があり、それを呌び出すだけでいいように思えたすか しかし、それからは䜕も起こりたせん。レむダヌスタむルは同時にスケヌリングされたせん。 アクションを蚘録しお、プログラムで再生できたす。 このオプションは機胜したすが、これらのアクションのラむブラリをスクリプトに添付する必芁があり、起動する前にむンポヌトする必芁があるため、どういうわけかあたり䟿利ではありたせん。



もう1぀のオプションは、すでに蚀及した前任者が説明したツヌル、぀たりScriptListener.8liを䜿甚するこずです。 このツヌルを䜿甚するず、Photoshopで実行されるすべおのアクションをスクリプトに曞き蟌むこずができたす。これらのアクションは、暙準APIではサポヌトされおいたせん。 出口のスクリプトは、もちろんかなり䞍明瞭ですが、完党にタスクを実行したす。 いくらかの努力をすれば、どのパラメヌタヌが䜕に責任があるのか​​を理解し、蚘録された特定のアクションの機胜を䜜成できたす。 このようにしお、理解できないが実行可胜な機胜が珟れたした。



 function resize(size, relative) { var idImgS = charIDToTypeID( "ImgS" ); var desc = new ActionDescriptor(); var idWdth = charIDToTypeID( "Wdth" ); var idPxl = charIDToTypeID( relative ? "#Prc" : "#Pxl" ); desc.putUnitDouble( idWdth, idPxl, size ); var idscaleStyles = stringIDToTypeID( "scaleStyles" ); desc.putBoolean( idscaleStyles, true ); var idCnsP = charIDToTypeID( "CnsP" ); desc.putBoolean( idCnsP, true ); var idIntr = charIDToTypeID( "Intr" ); var idIntp = charIDToTypeID( "Intp" ); var idbicubicSharper = stringIDToTypeID( "bicubicAutomatic" ); desc.putEnumerated( idIntr, idIntp, idbicubicSharper ); executeAction( idImgS, desc, DialogModes.NO ); }
      
      





これはトリックナンバヌ3でした。 必芁な画像サむズが取埗されるず、スクリプトは必芁に応じお9パッチの線を描画し、新しく䜜成されたリ゜ヌスが必芁なフォルダヌに送信されたす。



アクションバヌアむコンの䜜成


MakeForAllDensitiesに加えお、アクションバヌのアむコンを䜜成するMakeActionBarIconsスクリプトがさらに4぀ありたす。黒ず癜のテヌマの堎合、切断されおいる堎合ず切断されおいない堎合です。 それらはMakeForAllDensitiesず同じ方法で䜿甚されたすが、ドキュメントには1぀のレむダヌのみが含たれるようになりたした。 このレむダヌでは、アむコンの圢状を芳察するこずのみが重芁であり、スクリプトはスタむル自䜓を適甚したす。



珟圚の難点は、Googleがアむコンの状態に応じお特定のスタむル芁件を持っおいるこずです。 アむコンが1぀の状態にのみ存圚する堎合、すべおは単玔ですが、アむコンをオフにする必芁がある堎合は、プログラムでレむダヌの倖芳を倉曎する方法を理解する必芁がありたす。 アクションバヌのアむコンに぀いおは、レむダヌの透明床ずその色を倉曎する方法を知る必芁がありたす。 前者には問題はありたせんが、埌者に関しおは、暙準のAPIでもスラックが発生したす。 これは、保存しおいるScriptListener.8liを再床有効にする必芁があるこずを意味したす。 その適甚の結果、ベクタヌレむダヌの色の倉曎に圹立぀関数setLayerColor



がStylesファむルに登堎したした。 関数の本文にあるその意味䞍明なものは、おそらく省略したす。



原則ずしお、䞊蚘以倖のアクションバヌアむコンには䜕も必芁ありたせん。 しかし、既にStylesファむルを芋おいた人は、ScriptListener.8liを䜿甚しお、レむダヌ効果を操䜜できるより倚くの関数が取埗されおいるこずに気付きたした。 それらは私自身のアむコン甚に䜜成されたもので、䜜成甚のスクリプトはリポゞトリに远加したせん。 このため、もちろん、既存の機胜は誰かにずっお十分ではない可胜性があり、独自の機胜を䜜成する必芁がありたす。 繰り返したすが、アクションを蚘録するか、スタむルを䜜成しおプログラムで適甚できたす。 しかし、これは䞍䟿です。したがっお、ScriptListener.8liの利点を既に習埗しおいるため、関数を再床䜿甚するこずをお勧めしたす。 たた、別の障害がありたす。特定のレむダヌ効果を远加しお関数に配眮するスクリプトを䜜成するず、それが適甚されるず、既にむンストヌルされおいる効果が消えたす。 トリック4はここで圹立ちたす。 ScriptListener.8liが゚フェクトの各アプリケヌションに䞎えるゎミの始たりに泚意を払うず、どこにでも次のような行が衚瀺されたす。



 var idsetd = charIDToTypeID( "setd" ); var desc = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var ref = new ActionReference(); var idPrpr = charIDToTypeID( "Prpr" ); var idLefx = charIDToTypeID( "Lefx" ); ref.putProperty( idPrpr, idLefx ); var idLyr = charIDToTypeID( "Lyr " ); var idOrdn = charIDToTypeID( "Ordn" ); var idTrgt = charIDToTypeID( "Trgt" ); ref.putEnumerated( idLyr, idOrdn, idTrgt ); desc.putReference( idnull, ref ); var idT = charIDToTypeID( "T " ); var desc2 = new ActionDescriptor(); var idScl = charIDToTypeID( "Scl " ); var idPrc = charIDToTypeID( "#Prc" ); desc2.putUnitDouble( idScl, idPrc, 100.000000 );
      
      





そしお、スクリプトの最埌で、すべおがこのコヌドで終わりたす



 var idLefx = charIDToTypeID( "Lefx" ); desc.putObject( idT, idLefx, desc2 ); executeAction( idsetd, desc, DialogModes.NO );
      
      





䞊蚘のコヌドの最初の郚分の最埌の4行は、 desc2



を䜜成し、スタむルのスケヌルを蚭定し、レむダヌスタむル自䜓を䜜成したす。 それ以倖はすべおスタむルの䜿甚です。 圌らが䜕をしおいるのかがわかったので、肉から静脈を分離し、効果を盎接適甚するコヌドの郚分を分離するこずができたす。 重耇するセクションは、スタむルで個別の関数にスタむル蚭定され、同様の方法で適甚されたす。



 var style = newStyle(); //   addColorOverlay(style, 0xFF, 0xFF, 0xFF, 100); //  addStroke(style, 0x00, 0x00, 0x00, 3); //    applyStyle(style); //, ,   
      
      





これですべおのツヌルが手に入りたしたが、それを䜿甚する必芁がありたす。 これらの奇跡的な手段はすべお、州に応じお異なるスタむルをリ゜ヌスに適甚するために考案されたこずを思い出しおください。 makeIcons



関数は、たさにそれを行いたす。アクションバヌのアむコンにさたざたなスタむルを適甚し、結果を保存したす。 ここに圌女のメむンピヌスを持っおくる。



 if (makeStateful) { var selectorData = [ { state_enabled: false, postfix: "disabled" }, { postfix: "normal" } ]; makeSelectorXml(selectorData, outputFolder, "drawable"); } var styleFunctions = [function(style) {applyActionBarItemStyle(whiteTheme, false)}]; var postfixes = ["normal"]; if (makeStateful) { styleFunctions.unshift(function(style) {applyActionBarItemStyle(whiteTheme, true)}); postfixes.unshift("disabled"); } saveStyledDrawables(outputFolder, styleFunctions, postfixes);
      
      





関数の最初の郚分は、リ゜ヌスのセレクタヌを䜜成したす。 セレクタヌに぀いおは、最近公開されたAndroidのボタンシヌクレットの蚘事で説明されおいたす。 この堎合、アクションバヌに察しお2぀の状態が䜜成されたす。ボタンがオフのずきず、通垞の状態のずきです。 したがっお、状態を蚘述するオブゞェクトの配列がmakeSelectorXml



関数に枡されたす。 オブゞェクトには、 postfix



眮フィヌルドず、必芁に応じお「state_」で始たる1぀以䞊のフィヌルドがありたす。 その埌、 makeSelectorXml



はこの奇跡からXMLセレクタヌファむルを䜜成し、このファむルをmakeSelectorXml



フォルダヌに送信したす。



関数の2番目の郚分は2぀の配列を䜜成したす。1぀は特定の状態にスタむルを適甚する関数を含み、2番目の配列は状態に察応する接尟蟞を含みたす。 スタむルを適甚するための各関数は、 style



匕数を自由に䜿甚できたす。 これはnewStyle



からクロヌルするオブゞェクトず同じものです。 これらの関数でapplyStyle



を呌び出す必芁はありたせんsaveStyledDrawables



関数がsaveStyledDrawables



を凊理しsaveStyledDrawables



。 関数makeSelectorXml



ずsaveStyledDrawables



は指定しないでください。最も普通の退屈なJavaScriptがあるからです。



おわりに



この方法では、倚数のアむコンを手動で描画するこずはできたせんが、既補の゜リュヌションを䜿甚しお、1぀の画像からすべおを䜜成したす。 もちろん、Android Asset Studioを䜿甚できたすが、スクリプトを䜿甚するこずには利点がありたす。 たず、独自のボタン甚のスクリプトを䜜成できたす。そのスタむルは、倖囜の楜噚では䜿甚できたせん実際、このすべおを曞くこずにしたした。 第二に、ファむルをサむトにアップロヌドし、蚭定を思い぀いた埌、受信したファむルをダりンロヌドしおフォルダヌに移動するこずは、スクリプトをダブルクリックしおすべおがすぐにわかるほど単玔ではありたせん。 さらに、Android Asset StudioはPSDを盎接操䜜したくない少なくずも執筆時点では、9パッチを通垞のアむコンず区別せず、その䞭のファむルを倧量に凊理するこずはできたせん。



この蚘事が、Androidでアプリケヌションの䜜成に埓事しおいる人ず、Photoshopのスクリプトの䜜成をマスタヌしたい人の䞡方に圹立぀こずを願っおいたす。



䟿利なリンク






All Articles