Here it is! Animated icons!
Here it is! Animated icons!
This is something I’ve been making since some weeks, and in fact I finished before the current stable version started with the betas. But unfortunately I needed a way to choose a file, and the awesome lollipop file picker doesn’t return the path of the picked file. So I instead used Lighting’s file picker, which had some bugs fixed in the current version 😉 {Did someone notice the animated icon on my previous script video ‘Dynamic editor’? }
Currently the script can only use .gif files, but if you know any icon pack with animated icons that are not gifs, tell me and I’ll try with that. Also if you know an icon pack of gif files tell us in comments, as I could only find this one: https://web.archive.org/web/20150320083052/http://www.redworks.com/en/free-flat-animated-icons (NOTE: the site seems to be now a different one. For this reason the link is from the web archive)
The instructions are easy: run the script from the icon, choose a gif file, and accept if you want it to be automatically animated (otherwise you’ll need to set the script to an event). If your want to change to another gif file, just run the script again.
Important: the launcher keeps the reference of the gif file. If you remove it or change it’s path it will prompt an error.
Note: the more animated icons you have, the slower they all will become. You can change the fps in the script if necessary.
{In the video there are 13 animated icons simultaneously, and they still play at a good rate.}
Technical details:
A Movie file is created with the path chosen as parameter.
Successive timeouts are fired which draws that Movie in the live image of the icon.
]]>
< ![CDATA[
var fps=60;//frames per second
//classes
LL.bindClass(“android.graphics.Movie”);
LL.bindClass(“android.content.ContentResolver”);
LL.bindClass(“android.provider.MediaStore”);
//tags
var tagpath=”anicon”;
var tagid=”aniconid”;
//global vars
var thisscript=LL.getCurrentScript();
var item=null;
var source=””;
//when used startActivityForResult
if(typeof resultCode!=’undefined’){
if(!filechosen()) return;
}else{
//when launched from event
item=LL.getEvent().getItem();
source=LL.getEvent().getSource();
}
if(item==null) return;
if(source==”I_PAUSED”){
stop();
return;
}
//file
var path=item.getTag(tagpath);
if(path==null||source==”MENU_ITEM”){
choosefile();
return;
}
//start token
var gif=Movie.decodeFile(path);//gif movie
if(gif == null){
if(confirm(“The gif file couldn’t be found. Did you removed it or renamed a parent folder?\n(saved path: ‘”+path+”‘)\n Do you want to choose another one?”))choosefile();
return;
}
var t=gif.duration()*Math.random();//the current time of the movie, random start
fps=1000/fps;
var im=item.getImage();
var size=[im.getWidth(),im.getHeight()];//size of the live image
var oldid=item.getTag(tagid);
var id;
do{id=Math.random();}while(id==oldid);
item.setTag(tagid,id);//unique token
//start of the animation loop
update();
function stop(){
item.setTag(tagid,”-1″);//stop animation
}
function update(){
if(LL.isPaused()){
//launcher paused
stop();
return;
}
if(id!=item.getTag(tagid)){
//another instance of this script is fired
return;
}
var nim=LL.createImage(size[0],size[1]);
//var nim=i.getImage();
var nc=nim.draw();
nc.scale(nim.getWidth()/gif.width(),nim.getHeight()/gif.height());
gif.setTime(t)
gif.draw(nc,0,0);//draws the corresponding image
nim.update();
item.setImage(nim);
t=(t+fps)%gif.duration();
setTimeout(update,fps);//repeat
}
function choosefile(){
var intent =new Intent();
intent.setComponent(ComponentName.unflattenFromString(“net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.FilePicker”));//file picker activity
intent[‘putExtra(java.lang.String,java.lang.String[])’](“e”,[“gif”]);//list of extensions to show
if(thisscript.getTag()!=null)intent.putExtra(“p”,thisscript.getTag());//path where to start
LL.startActivityForResult(intent,thisscript,item.getId());
}
function filechosen(){
if(data==null){
Android.makeNewToast(“Cancelled”,true).show();
return false
}
var dp=data.getExtra(“p”);//last path opened
var df=data.getExtra(“f”);//file chosen
if(dp!=null)thisscript.setTag(data.getExtra(“p”));//so next time it will open in the previous path
if(df==null){
Android.makeNewToast(“No file picked”,true).show();
return false
}
//otherwise gif chosen
item=LL.getItemById(token);
item.setTag(tagpath,df);//saved path
item.setCustomIcon(LL.createImage(df));//this makes the item to have a custom icon related to the animated one
if(confirm(“Do you want it to be automatically animated?\n(script in the resumed/paused event)”)){
//it make this for you
item.getProperties().edit()
.setEventHandler(“i.resumed”,EventHandler.RUN_SCRIPT,thisscript.getId())
.setEventHandler(“i.paused”,EventHandler.RUN_SCRIPT, thisscript.getId())
.commit();
}
return true;
}
]]>
< ![CDATA[
Awesome! Now I have to make some gifs.
]]>
< ![CDATA[
Mind = Blown to shreds. This is awesome! :3
]]>
< ![CDATA[
Hey TrianguloY, what’s up with that link?
Takes me to H&O. Is that correct?
]]>
< ![CDATA[
Yeah what gives?
]]>
< ![CDATA[
TrianguloY absolutely amazing! Chris Chastain you took the words right out of my mouth. It’s time to do ome of my favorite things…animate. Hey TrianguloY, how would I set it only to selected image, so that it only plays the animation when I click on it?
]]>
< ![CDATA[
Thomas Greer i cant even get my gif files to show let alone animate.
]]>
< ![CDATA[
uhm? but that was the link….maybe the page has gone since I visited it?
I’ll investigate. If I can’t find the original link I’ll post the files.
]]>
< ![CDATA[
So, it seems the site is now owned from another company or whatever. I could find the original site in the web Archive.
Link updated (you can still download the icons there)
]]>
< ![CDATA[
How did you get that circular selection animation thing?
]]>
< ![CDATA[
TrianguloY i apply the icons and they disappear.
]]>
< ![CDATA[
James Coyle Material effect (android 5.0+)
Curtis Sylvester Jr. which android version are you using?
]]>
< ![CDATA[
4.1.1
]]>
< ![CDATA[
Anyone else with that version can check?
When you say the items disappear, what do you mean? Which icons, the ones on the link?
]]>
< ![CDATA[
To answer your question the only thing i can say is “pick one”. doesnt even have to be one of the animated icons. No matter what .gif i use it disappears.
Im thinking its because i dont have a 5.0+ and that theory is based on the fact that almost nobody runs a 4.x anymore. I seem to be the only one
]]>
< ![CDATA[
TrianguloY thought it was 🙁 still haven’t received the update.
]]>
< ![CDATA[
Curtis Sylvester Jr. Yep, just you and me on 4.0.4. Hehe!
]]>
< ![CDATA[
I’m sure you are not alone, maybe here is not the best place to search
I have a tablet with 4.2.2, and you are right, the icon disappear.
I’m working on a fix, I’ll let you know
]]>
< ![CDATA[
Android 4.4.4 and running this wow factor script without problems. Thank you for making this possible.
]]>
< ![CDATA[
Well I’ll be damned… Nice work TrianguloY
]]>
< ![CDATA[
/*
Those who have issues with dissapeared icons, try this modification.
If it now works tell me and I’ll update the main post 🙂
*/
var fps=60;//frames per second
var fix = true; //set this to true if you see no image
//classes
LL.bindClass(“android.graphics.Movie”);
if(fix){
LL.bindClass(“java.io.FileInputStream”);
LL.bindClass(“java.io.ByteArrayOutputStream”);
LL.bindClass(“java.lang.Byte”);
LL.bindClass(“java.lang.reflect.Array”);
}
//tags
var tagpath=”anicon”;
var tagid=”aniconid”;
//global vars
var thisscript=LL.getCurrentScript();
var item=null;
var source=””;
//when used startActivityForResult
if(typeof resultCode!=’undefined’){
if(!filechosen()) return;
}else{
//when launched from event
item=LL.getEvent().getItem();
source=LL.getEvent().getSource();
}
if(item==null) return;
if(source==”I_PAUSED”){
stop();
return;
}
//file
var path=item.getTag(tagpath);
if(path==null||source==”MENU_ITEM”){
choosefile();
return;
}
//start token
var gif;
if(fix){
//some android 4.x have problems with decodeFromPath
var array = streamToBytes( new FileInputStream(path) );
gif= Movie.decodeByteArray(array, 0, array.length); //gif movie
}else{
gif=Movie.decodeFromFile(path);//gif movie
}
if(gif == null){
if(confirm(“The gif file couldn’t be found. Did you removed it or renamed a parent folder?\n(saved path: ‘”+path+”‘)\n Do you want to choose another one?”))choosefile();
return;
}
var t=gif.duration()*Math.random();//the current time of the movie, random start
fps=1000/fps;
var im=item.getImage();
var size=[im.getWidth(),im.getHeight()];//size of the live image
var oldid=item.getTag(tagid);
var id;
do{id=Math.random();}while(id==oldid);
item.setTag(tagid,id);//unique token
//item.getRootView().getChildAt(0).setLayerType(View.LAYER_TYPE_SOFTWARE,null);
//start of the animation loop
update();
function stop(){
item.setTag(tagid,”-1″);//stop animation
}
function update(){
if(LL.isPaused()){
//launcher paused
stop();
return;
}
if(id!=item.getTag(tagid)){
//another instance of this script is fired
return;
}
var nim=LL.createImage(size[0],size[1]);
//var nim=i.getImage();
var nc=nim.draw();
nc.scale(nim.getWidth()/gif.width(),nim.getHeight()/gif.height());
gif.setTime(t)
gif.draw(nc,0,0);//draws the corresponding image
nim.update();
try{
item.setImage(nim);
}catch(e){
stop();//item not found, deleted?
}
t=(t+fps)%gif.duration();
setTimeout(update,fps);//repeat
}
function choosefile(){
//using Lightning file picker because android one on latest android versions return ‘content://…’ that can change when restarting phone
var intent =new Intent();
intent.setComponent(ComponentName.unflattenFromString(“net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.FilePicker”));//file picker activity
intent[‘putExtra(java.lang.String,java.lang.String[])’](“e”,[“gif”]);//list of extensions to show
if(thisscript.getTag()!=null)intent.putExtra(“p”,thisscript.getTag());//path where to start
LL.startActivityForResult(intent,thisscript,item.getId());
}
function filechosen(){
if(data==null){
Android.makeNewToast(“Cancelled”,true).show();
return false
}
var dp=data.getExtra(“p”);//last path opened
var df=data.getExtra(“f”);//file chosen
if(dp!=null)thisscript.setTag(data.getExtra(“p”));//so next time it will open in the previous path
if(df==null){
Android.makeNewToast(“No file picked”,true).show();
return false
}
//otherwise gif chosen
item=LL.getItemById(token);
item.setTag(tagpath,df);//saved path
item.setCustomIcon(LL.createImage(df));//this makes the item to have a custom icon related to the animated one
if(confirm(“Do you want it to be automatically animated?\n(script in the resumed/paused event)”)){
//it make this for you
item.getProperties().edit()
.setEventHandler(“i.resumed”,EventHandler.RUN_SCRIPT,thisscript.getId())
.setEventHandler(“i.paused”,EventHandler.RUN_SCRIPT, thisscript.getId())
.commit();
}
return true;
}
function streamToBytes(is) {
var os = new ByteArrayOutputStream(1024);
var buffer =Array.newInstance(Byte.TYPE,1024);
var len;
try {
while ((len = is.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (e) {
alert(e);
}
return os.toByteArray();
}
]]>
< ![CDATA[
SUCCESS the first .gif i tried worked. I dont know howSteve Harvey hasnt been shot by his wife yet hahahaha
]]>
< ![CDATA[
With this adapted for normal background for blank item, we could have a animated bar. Is that correct. Could that be possible?
]]>
< ![CDATA[
Evelien Wijbenga yes, will be.
That gave me an idea. I’ll try to make it compatible with boxbackground only changing a var to true 🙂
]]>
< ![CDATA[
Cool thanks. TrianguloY
]]>
< ![CDATA[
/*
Evelien Wijbenga check this (change the fix var if you need it to false)
*/
var fps=60;//frames per second
var useBackground=true;//set this to true to set the gif in the box background, otherwise the icon is used
var fix = false; //set this to true if you see no image
//classes
LL.bindClass(“android.graphics.Movie”);
if(fix){
LL.bindClass(“java.io.FileInputStream”);
LL.bindClass(“java.io.ByteArrayOutputStream”);
LL.bindClass(“java.lang.Byte”);
LL.bindClass(“java.lang.reflect.Array”);
}
//tags
var tagpath=”anicon”;
var tagid=”aniconid”;
//global vars
var thisscript=LL.getCurrentScript();
var item=null;
var source=””;
//when used startActivityForResult
if(typeof resultCode!=’undefined’){
if(!filechosen()) return;
}else{
//when launched from event
item=LL.getEvent().getItem();
source=LL.getEvent().getSource();
}
if(item==null) return;
if(source==”I_PAUSED”){
stop();
return;
}
//file
var path=item.getTag(tagpath);
if(path==null||source==”MENU_ITEM”){
choosefile();
return;
}
//start token
var gif;
if(fix){
//some android 4.x have problems with decodeFromPath
var array = streamToBytes( new FileInputStream(path) );
gif= Movie.decodeByteArray(array, 0, array.length); //gif movie
}else{
gif=Movie.decodeFile(path);//gif movie
}
if(gif == null){
if(confirm(“The gif file couldn’t be found. Did you removed it or renamed a parent folder?\n(saved path: ‘”+path+”‘)\n Do you want to choose another one?”))choosefile();
return;
}
var t=gif.duration()*Math.random();//the current time of the movie, random start
fps=1000/fps;
var size;
if(useBackground){
size=[item.getWidth(),item.getHeight()];
item.setBoxBackground(LL.createImage(size[0],size[1]),”n”);
}else{
var im=item.getImage();
size=[im.getWidth(),im.getHeight()];//size of the live image
}
var oldid=item.getTag(tagid);
var id;
do{id=Math.random();}while(id==oldid);
item.setTag(tagid,id);//unique token
//item.getRootView().getChildAt(0).setLayerType(View.LAYER_TYPE_SOFTWARE,null);
//start of the animation loop
update();
function stop(){
item.setTag(tagid,”-1″);//stop animation
}
function update(){
if(LL.isPaused()){
//launcher paused
stop();
return;
}
if(id!=item.getTag(tagid)){
//another instance of this script is fired
return;
}
//var nim=LL.createImage(size[0],size[1]);
var nim=useBackground?item.getBoxBackground(“n”):item.getImage();
if(nim==null){stop();return;}
var nc=nim.draw();
nc.drawColor(0);
nc.scale(nim.getWidth()/gif.width(),nim.getHeight()/gif.height());
gif.setTime(t)
gif.draw(nc,0,0);//draws the corresponding image
nim.update();
/*try{
item.setImage(nim);
}catch(e){
stop();//item not found, deleted?
}*/
t=(t+fps)%gif.duration();
setTimeout(update,fps);//repeat
}
function choosefile(){
//using Lightning file picker because android one on latest android versions return ‘content://…’ that can change when restarting phone
var intent =new Intent();
intent.setComponent(ComponentName.unflattenFromString(“net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.FilePicker”));//file picker activity
intent[‘putExtra(java.lang.String,java.lang.String[])’](“e”,[“gif”]);//list of extensions to show
if(thisscript.getTag()!=null)intent.putExtra(“p”,thisscript.getTag());//path where to start
LL.startActivityForResult(intent,thisscript,item.getId());
}
function filechosen(){
if(data==null){
Android.makeNewToast(“Cancelled”,true).show();
return false
}
var dp=data.getExtra(“p”);//last path opened
var df=data.getExtra(“f”);//file chosen
if(dp!=null)thisscript.setTag(data.getExtra(“p”));//so next time it will open in the previous path
if(df==null){
Android.makeNewToast(“No file picked”,true).show();
return false
}
//otherwise gif chosen
item=LL.getItemById(token);
item.setTag(tagpath,df);//saved path
item.setCustomIcon(LL.createImage(df));//this makes the item to have a custom icon related to the animated one
if(confirm(“Do you want it to be automatically animated?\n(script in the resumed/paused event)”)){
//it make this for you
item.getProperties().edit()
.setEventHandler(“i.resumed”,EventHandler.RUN_SCRIPT,thisscript.getId())
.setEventHandler(“i.paused”,EventHandler.RUN_SCRIPT, thisscript.getId())
.commit();
}
return true;
}
function streamToBytes(is) {
var os = new ByteArrayOutputStream(1024);
var buffer =Array.newInstance(Byte.TYPE,1024);
var len;
try {
while ((len = is.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (e) {
alert(e);
}
return os.toByteArray();
}
]]>
< ![CDATA[
Wait.. you mean it would be possible to have a animated desktop background?
]]>
< ![CDATA[
Curtis Sylvester Jr. Possible, yes. But maybe not very efficient. A dynamic wallpaper is the best option.
Anyway you can try with this latest modification and a full screen item
]]>
< ![CDATA[
Wow TrianguloY ill test it right away.
]]>
< ![CDATA[
I wasnt trying to do it, i just couldnt seem to figure out with this latest is for
]]>
< ![CDATA[
Curtis Sylvester Jr. Instead of setting the gif in the icon of the item, it sets it in its boxBackground
]]>
< ![CDATA[
Totally awesome. Works and looks great. Thanks TrianguloY.
I love eye candy.
]]>
< ![CDATA[
Btw. I noticed your animated bug icon at the end of your screen cast. Cool. That would be a nice feature for lightning launcher 😉
]]>
< ![CDATA[
So I jus copy and paste this, will it be all lined up right? I still haven’t tried a script really, almost did but couldn’t get something right lol
]]>
< ![CDATA[
I’ve been messing around with this, and now I want to disable it.
Any advice?
I can revert box background, but it doesn’t survive a restart.
Pause and resume event show unset.
]]>
< ![CDATA[
Chris Chastain not sure what you mean
The unmodified script changes the custom icon and the live image, and the latest modification changes the normal box background.
If the script is not in the events of the item it can’t make anything.
]]>
< ![CDATA[
TrianguloY, yes I know right? 🙂
I figured it out… Was in the wrong place. Still getting used to our new layout editor!
I was trying to set a large gif
to folder background and ended up setting it globally to the folder container items :-/
This is fun to play with. I need to figure out a cool way to use it now. Thanks!
]]>