Pages

    2010年9月24日金曜日

    iPadでお絵かき

    JSPaintがiPad対応してないので、
    どこまで出来るかちょっと調べてみました。

    ググると結構やられてるのでネタとしてはいまいちですが
    とりあえずコードをはっときます。

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="user-scalable=no, width=device-width">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>タッチテスト</title>

    <style>
    body{ margin:0;padding:0;}
    #canvas{ border:1px solid #009; margin:30px 30px 0;}
    #log{ width:650px; height:220px; overflow:scroll;}
    </style>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    </head>

    <body>
    <canvas width="450" height="250" id="canvas"></canvas>
    <div id="log"></div>
    <script>
    //参考:ASCII.jp:HTML5のCanvasで作る、Flash不要のお絵かきツール |古籏一浩のJavaScriptラボ http://ascii.jp/elem/000/000/513/513377/
    var off;
    var gapX;
    var gapY;
    var padd=30;
    var canvX;
    var canvY;
    var canvW;
    var canvH;
    var drawFlag = false;
    var oldX = 0;
    var oldY = 0;
    var $canvas;

    $(document).ready(function () {
            document.body.ontouchmove = function (e) { e.preventDefault(); };
            $canvas=$("#canvas");
            off=$canvas.offset();
            gapX=off.left;
            gapY=off.top;
            canvH=$canvas.attr('clientHeight');
            canvW=$canvas.attr('clientWidth');
            $canvas.bind("touchstart", touchStartHandler, false);
            $canvas.bind("touchmove", touchMoveHandler, false);
            $canvas.bind("touchend", touchEndHandler, false);
        });
        //タッチ開始
        function touchStartHandler(e){
            $("#log").text("touchstart");
             drawFlag = true;
                 // タッチ位置を取得
                    var fn=function(i){
                        oldX=e.originalEvent.touches[i].pageX-gapX;
                        oldY=e.originalEvent.touches[i].pageY-gapY;
                    }
        loop(e,fn);
            }
            //タッチして移動
        function touchMoveHandler(e){
            $("#log").text("touchmove");
        var fn=function(i){
                        canvX=e.originalEvent.touches[i].pageX-gapX;
                        canvY=e.originalEvent.touches[i].pageY-gapY;
                        //判定エリア内なら
                        if(canvX<=canvW+padd && canvY<=canvH+padd && canvX>=0-padd && canvY>=0-padd){

                        $("#log").text("X:"+ canvX+"Y:"+canvY);
                        //draw
                         if (!drawFlag) return;
                            var canv=document.getElementById("canvas");
                            var context =canv.getContext("2d");
                            context.strokeStyle = "rgba(220,220,220,0.7)";
                            context.lineWidth = 3;
                            context.beginPath();
                            context.moveTo(oldX, oldY);
                            context.lineTo(canvX, canvY);
                            context.stroke();
                            context.closePath();
                            oldX = canvX;
                            oldY = canvY;
                        }
        }
        loop(e,fn);
            }
            //タッチ終了
        function touchEndHandler(e){
            $("#log").text("touchend");
             drawFlag = false;
            }
        /*function touchCancelHandler(e){
            $("#log").text("touchcancel");
            }*/
            //ループ
        function loop(e,fn){
            for (var i = 5; i--;) {
                    if (e.originalEvent.touches[i]) {
                        fn(i)
                    }
                }
            }

    </script>
    </body>
    </html>

    参考:


    2010年8月24日火曜日

    ViewFlipperでテキストアニメーション


    API DEMOSのViews/Animation/Pushにテキストがニュースヘッダーのようにアニメするサンプルがあります。それをいじってボタンを押したら(もしくは何らかのイベントで)アニメが動くようにしてみました。アニメの部分をクラスにしてまとめたので、いじりやすくなったんじゃないかと思ってます。(あくまで自己満足)

    ソースはアニメのクラスとそれを呼び出す部分の2つです。(レイアウト、アニメなどXMLは除く)

    注)以下のコードはLogCatにずっと実行されてるみたいな挙動だったので使わないでね。直したものを最後に張っておきます。

    以下だめだめ
    呼び出し側
    package com.yoropan.TextAnimation;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.ViewFlipper;
    
    public class TextAnimation extends Activity {
    
     private ViewFlipper mFlipper;
    
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      final TextView stats = (TextView) findViewById(R.id.stats);
      final TextView stats2 = (TextView) findViewById(R.id.stats2);
      stats.setText("aaaaaaa");
      stats2.setText("bbbbbbbbbb");
    
      Button btn = (Button) findViewById(R.id.change);
      Button btn2 = (Button) findViewById(R.id.change2);
      
      mFlipper = (ViewFlipper) findViewById(R.id.flipper);
      
      btn.setOnClickListener(new View.OnClickListener() {
    
        DoFlipper d=new DoFlipper(TextAnimation.this);
       public void onClick(View v) {
       d.pushup(mFlipper);//上に動け
       }
    
      });
      btn2.setOnClickListener(new View.OnClickListener() {
       public void onClick(View v) {
         DoFlipper d=new DoFlipper(TextAnimation.this);
        d.pushdown(mFlipper);//下に動け
        
       }
      });
     }
     
     
     
    }
    

    アニメの方のクラス
    package com.yoropan.TextAnimation;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    
    import android.app.Activity;
    import android.view.animation.AnimationUtils;
    import android.widget.ViewFlipper;
    
    public class DoFlipper {
     
     Timer timer = null;
     // ハンドラ
     android.os.Handler handler = new android.os.Handler();
     
     private Activity activity;
     public DoFlipper(Activity activity) {
      this.activity=activity;
      }
     void pushup(ViewFlipper mFlipper) {
      mFlipper.startFlipping();
      mFlipper.setInAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_up_in));
      mFlipper.setOutAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_up_out));
      mFlipper.showNext();
      timestop(mFlipper);//stop
      // mFlipper.setAnimation(AnimationUtils.loadAnimation(TextAnimation.this, R.anim.push_up));
      
     }
      void pushdown(ViewFlipper mFlipper) {
      mFlipper.startFlipping();
      mFlipper.setInAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_down_in));
      mFlipper.setOutAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_down_out));
      mFlipper.showNext();
      timestop(mFlipper);//stop
     }
     private void timestop(final ViewFlipper mFlipper) {
      // タイマの設定
      timer = new Timer(true);
      timer.schedule( new TimerTask() {
    
       public void run() {
    
        // 表示の更新
        handler.post( new Runnable() {
         public void run() {
          mFlipper.stopFlipping();
          //pushdown();
         }
        });
    
       }
    
      }, 1000, 1000 );
     }
    }
    
    

    以下LogCatで確認したOKなやつ
    呼び出し側
    package com.yoropan.TextAnimation;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.ViewFlipper;
    
    public class TextAnimation extends Activity {
    
     public static ViewFlipper mFlipper;
    
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      final TextView stats = (TextView) findViewById(R.id.stats);
      final TextView stats2 = (TextView) findViewById(R.id.stats2);
      stats.setText("aaaaaaa");
      stats2.setText("bbbbbbbbbb");
    
      Button btn = (Button) findViewById(R.id.change);
      Button btn2 = (Button) findViewById(R.id.change2);
      
      mFlipper = (ViewFlipper) findViewById(R.id.flipper);
      
      btn.setOnClickListener(new View.OnClickListener() {
    
        DoFlipper d=new DoFlipper(TextAnimation.this);
       public void onClick(View v) {
       d.pushup();//上に動け
       }
    
      });
      btn2.setOnClickListener(new View.OnClickListener() {
       public void onClick(View v) {
         DoFlipper d=new DoFlipper(TextAnimation.this);
        d.pushdown();//下に動け
        
       }
      });
     }
     
     
     
    }
    

    アニメの方のクラス
    package com.yoropan.TextAnimation;
    
    import android.app.Activity;
    import android.view.animation.AnimationUtils;
    import android.widget.ViewFlipper;
    
    public class DoFlipper {
     ViewFlipper mFlipper=TextAnimation.mFlipper;
     
     private Activity activity;
     public DoFlipper(Activity activity) {
      this.activity=activity;
      }
     void pushup() {
      mFlipper.startFlipping();
      mFlipper.setInAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_up_in));
      mFlipper.setOutAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_up_out));
      mFlipper.showNext();
      mFlipper.stopFlipping();
      
     }
      void pushdown() {
      mFlipper.startFlipping();
      mFlipper.setInAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_down_in));
      mFlipper.setOutAnimation(AnimationUtils.loadAnimation(activity, R.anim.push_down_out));
      mFlipper.showNext();
      mFlipper.stopFlipping();
     }
    
    }
    

    タイマーをかませると見た目はとまってるんだけどログには出続けるのでなんか気持ち悪かった(たぶん電池とか消費するんだろうな)ので直しました。

    2010年6月9日水曜日

    Android Bazaar and Conference 2010 Spring

    行きます。



    イベント/Android Bazaar and Conference 2010 Spring - 日本Androidの会(日本アンドロイドの会)


    日時
    2010年6月26日(土)

    10:00~18:00 (受付開始 9:30)

    会場
    東京大学駒場キャンパス13号館1階(総合受付)

    〒153-8902 東京都目黒区駒場3-8-1(京王井の頭線 駒場東大前駅)

    http://www.u-tokyo.ac.jp/campusmap/cam02_01_12_j.html

    2010年3月10日水曜日

    ROKONのパーティクルサンプル

    Example16にBasic Particle Systemというデモがあったので中身を見てみた。

    以下ソースの抜粋
        public Emitter carEmitter;
        public void onCreate() {
            createEngine(480, 320, true);
        }

        @Override
        public void onLoad() {
            atlas = new TextureAtlas(512, 512);
            atlas.insert(backgroundTexture = new Texture("graphics/backgrounds/beach.png"));
            atlas.insert(carTexture = new Texture("graphics/sprites/car.png"));
            TextureManager.load(atlas);
            background = new FixedBackground(backgroundTexture);
            carEmitter = new Emitter(-10, 10, -10, 10, 4, 8, carTexture);
    //秒間最大8生成している(第6引数)
            carEmitter.addParticleModifier(new ParticleDimensions(50, 90, 50, 90));
            carEmitter.addParticleModifier(new ExpireParticle(2700, 3500));
            carEmitter.addParticleModifier(new AccelerateParticle(100, 200, 50, 100));
        }

        @Override
        public void onLoadComplete() {
            rokon.setBackground(background);
            rokon.addEmitter(carEmitter);
            carEmitter.startSpawning();
        }

    Spawningってなんやろーと翻訳すると「産卵」ですって。なるほど。
    N1で動かしてみたけどキャプチャが変になりました。動作自体はいけてる感じです。HT-03Aだと…がんばってますって感じですね。

    2010年3月8日月曜日

    aLDClipの明示的インテント

    以下のようにして使えます。

    package com.yoropan.IntenTest;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;

    public class IntenTest extends Activity {
        Button send;
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
         send=(Button)findViewById(R.id.send);
         send.setOnClickListener(clk);
        }
       private View.OnClickListener clk=new View.OnClickListener(){
               //明示的intent
               Intent intent=new Intent(Intent.ACTION_SEND);
               intent.setClassName("com.yoropan.aLDClip","com.yoropan.aLDClip.LDClip");
               intent.putExtra(Intent.EXTRA_SUBJECT,"タイトルだよー");
               intent.putExtra(Intent.EXTRA_TEXT,"http://www.google.com");
               intent.setType("text/plain");
               startActivity(intent);
           }
        };
    }

    結果)

    以上です。よろしくお願いします。

    2010年2月23日火曜日

    androidのレイアウト

    苦戦中。

    LinearLayoutだろうがRelativeLayoutだろうが画面外に出てしまう。
    動的に要素を増やしたときはどうすればいいのだろう。tableレイアウトになるのかなー?。HTMLのインライン要素みたいにはじっこでいい感じに折り返してくれないのかしら。。。

    あとflashだと変数に連番とか振るのだけど、以下のようにしたらウィジェットを動的に複数個作成できた[謎]。普通なんだろうかこれ?

    String[] arr={"aaa","bbb","ccc","ddd","eee"};
            for (int i = 0; i < arr.length; i++) {
                CheckBox checkBox = new CheckBox(this);
                checkBox.setText(arr[i]);
                layout.addView(checkBox);
            }

    2010年2月17日水曜日

    RatingBarのバグ

    SDKのバージョン3でRatingBar(☆☆☆☆☆)を使うとNexusOneやDroidで表示が欠けてしまう

    簡単な解決方法はSDKのバージョンを4(OSでは1.6)にすることみたい。

    RatingBar size issues on high-density screens (Droid, Nexus One) - Android Developers | Google グループ http://groups.google.co.jp/group/android-developers/browse_thread/thread/e91df884f7c056ea?pli=1

    URLを短縮する

    短縮サービスを試して結局TinyURLにした。

    bit.lyはAPIを使うのにアカウントが必要でユーザーも自分も気持ち悪かろうということでやめ、short.toは長いURLが切れてだめだった。自分のやり方が悪いのかも知れんけど。

    以下、参考にしました。

    TinyURL の api を使う - monaurallab (モノラルラボ) http://d.hatena.ne.jp/matsuoshi/20090407/1239078125

    [Android] Android からbit.ly短縮URLサービスを使ってみた –adakoda
    http://www.adakoda.com/adakoda/2010/01/android-android-bitlyurl.html

    2010年2月16日火曜日

    livedoorクリップのURL文字数制限

    Android用のLivedoorクリップクライアントの進捗状況。

    クリップ機能を実装できたのだけどlivedoorクリップの仕様なのか手元では94文字までしか判別できない。。。まじか?

    あとURLにがすでにURLエンコードしてある文字列があるとエラーが帰ってくるっぽい?

    URLをbit.lyとかの短縮URLとかに通すしかないのかなー。

    これをクリアすれば公開できるかなー。

    2010年1月25日月曜日

    FireworksのPSD保存で気をつける点

    Fireworks CS4 - Saving As PSD Files http://blog.blue2x.com/?p=871 に載ってました。

    Tip 1 – いくつかのグラデーションタイプはPsで開けないのでビットマップ化する。

    Tip 2 – FwのデフォルトのフィルタもPsでは問題になる。完全ではないがPhotoshopライブエフェクトを使えばPSDファイルにしたときに取り回し出来る

    Tip 3 – いくつかのレイヤーモードはPsに存在しない。レイヤーモードにこだわるならビットマップ化する。

    Tip 4 – グループも問題になるので保存する前にグループ解除する

    Tip 5 – PSDで保存するときオプションを選択する(カスタム設定にすれば、オブジェクト、効果、ベクトル、テキストについて編集を重んじるか外観を重んじるか設定できる)

    Tip 6 – 出来るだけシンプルに。ビットマップ化なしでPsに書き出すときはグラデーションはなるべく選ばずベタ塗りにする。

    以上翻訳メモ。

    2010年1月23日土曜日

    Chromeが突然エラー画面を出しまくるので調べてみた



    エラー画面さんがでまくるようになったのでヘルプにしたがってUser Dataをバックアップして原因をさぐってみた。

    結果として機能拡張のGoogle Translateを切ると正常に動くようになった。



    エラーが出る人は試してみてください。

    User Data\Default\Preferencesを開いてみるとテキスト(json?)形式でそこに機能拡張の設定が書いてあった。他にもテーマの設定もかいてあったり。面白いですね。

    2010年1月21日木曜日

    標準ブラウザのコンテントプロバイダから履歴を取得

    ブラウザのタイトルを得るのにURLから実際にアクセスしてtitleを得る方法でもいいんですが、スマートじゃないので他に方法がないか探してみました。
    「つんどく」がやっているみたいに履歴をどこからかひっぱて来れないか調べてみるとコンテントプロバイダを使うみたい。

    Bookmarkを取得したい http://bamleace.jimdo.com/android/webview%E9%80%86%E5%BC%95%E3%81%8D/

    履歴自体はどうやってとるのか良く分からなかったのだけど、どうやらBrowser.BookmarkColumns.DATEでとるみたい。コンテントプロバイダはDBのデータ取得見たいな感じ。ソート部分をBrowser.BookmarkColumns.DATE+" DESC"にすると新着順で履歴としてデータを取得できる。

    device100121 device100121_2
    左:今回試したもの 右:ブラウザ履歴

    参考:Content Providerの利用 > みゅお(muo_jp)によるAndroidのドキュメント翻訳 http://www.muo.jp/android/?devel/data/contentproviders.html

    調べてて分かったけど「よく使用」ダブの表示基準はBrowser.BookmarkColumns.VISITSから表示回数が取れたんでそれで表示してるんかなー。

    2010年1月20日水曜日

    livedoorクリップ for Androidを作りたい

    livedoorクリップのアプリがandroidマーケット探してみてもなさそうなので勉強がてら作ってみるかーのめも。
    livedoorクリップ自体のapiはdelicious互換らしいのでそっちの方のオープンソースアプリを探したらありました。

    android-delicious-bookmarks - Project Hosting on Google Code http://code.google.com/p/android-delicious-bookmarks/

    ただ使ってみると日本語タイトルが化けてしまう。
    どういう処理をしているのか見てみるとページのタイトルを取るのに
    URLからBufferedReaderというのでアクセスしてソースを取得のあとtitleタグをindexOfで拾ってきてるみたい。(WebPageTitleRequest.java)

    これがUTF-8以外は文字化けするようなので、直すか別のやり方でやらないとだめなんかなぁ。

    そんな中、BIGLOBEがBIGLOBEゲートβを開設、あとでよむアプリ「つんどく」をリリースしたそうなので入れてみた。ノティフィケーションに常駐してブラウザの履歴や最終ページから登録する形のようだ。
    device 
    もちろん文字も化けていない。どういう作り方なんだろうか。。。

    調べなおしたらこんな感じでいけるみたい。
    InputStreamReaderの第二引数が文字コードセットできるみたいですね。

    2010年1月13日水曜日

    Android開発の本

    海外ですが3冊ともソースコードが公開されているので参考になると思います。 http://commonsware.com/books

    和書ではこれは要チェックですね。

    2010年1月12日火曜日

    Android用の2D用OpenGLゲームエンジンなんてあるのね

    とりあえず勉強するのにサンプルが必要なので
    Androlibで「open source」で検索して良さげなものをeclipseにSVNでゲットする。

    検索して思わぬものを見つけた。
    Android用の2D用OpenGLゲームエンジンだそうだ >rokon
    まぁOpenGLは全然わからないので使いたくても使えないという。
    ただ以前調べたらパーティクルエンジンをAndroidで走らせたら超重くて使えんみたいなことが書いてあったのでこのライブラリで解決できそうかも?
    この辺のリソースが増えていくとAndroidでゲームも増えておもしろくなるんかなー。

    あと半年もすれば日本でFlashPlayerのったAndroid端末が出ると思われます。
    ネット上のFlashゲームは無料だけど広告が挟まれるのが多いですね。
    @Nifty、bigrobe、ハンゲーム、モゲラを回ってみたけど割と楽しめそうな感じです。
    ちなみにおすすめはtaitoさんのこれ
    画面サイズは640x480サイズに近いサイズが一般的みたいです。
    Nexus Oneの画面解像度は800x480らしいので解像度的には問題ないですね。

    そういえばAndroid マーケットにFlashゲーム(をjavaでラップする形になる?)のせられるようになるんだろうか?Adobeさん次第だけど。

    2010年1月11日月曜日

    グラフィックデザイナーのためのAIRという記事を物色

    47 Useful Adobe AIR Apps for Web and Graphic Designers : Speckyboy Design Magazineというのを見て適当にAIRアプリをDLしてみた。
    使えそうかなーと思ったのが次の2つ
    designview


    ソースも書き出してくれる

    builder立ち上げなくてもさくっと画面作るだけなら使えるかも。あとFlexわからんデザイナーとかに使わせてみるとか。まぁわかる人が横にて解説は必要かもしれんけど。

    DOC?

    ローカル、ネット上の複数リファレンスを管理できるアプリ。flashとeclipseから起動できるプラグインがある。
    普段よく使うASDOCSを登録しとくと便利かも。クラス、プロパティ、イベントなどをアイコン表示してくれて、串刺し検索もできる。日本語表示に弱いところがある。