【css】imgやvideoをアスペクト比を保ちつつ画面一杯に表示する

はじめに

機会ないかもしれないけど次やるときのためのメモ。
やりたいのはスマホでこんな感じの画面。画像でも動画でも同じcssで。

横画像


portrait
20170127094740

landscape

縦画像


portrait
20170127094930

landscape
20170127094930

実装

htmlはどちらの動画も共通で、cssは横長と縦長とでそれぞれ用意する。

html

<div id="wrapper">
  <img src="/path/to/file" />
</div>

320x180(横長)のcss

body {
  margin:0;
}

#wrapper {
  position:relative;
  width: 100%;
  height:100%;
  background-color:black;
}

#wrapper > img {
  width: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

400x625(縦長)のcss

body {
  margin:0;
}

#wrapper {
  height: 100%;
  text-align:center;
  background-color:black;
}

#wrapper > * {
  height: 100%;
}

以上です

【android】apiへリクエストしてcallbackを実装する方法メモ

はじめに

android調べながらやってるけどJavaの基礎もあんまないから時間かかる。
今回やりたいのはapiたたいてレスポンスによって成功用と失敗用のcallbackを実行するようなこと。
調べたり質問しながらやってるけどinterface使うといいらしい。

実装1

呼び出し側に成功時と失敗時のコールバック用インターフェスを実装させる。
すっきりしてる気もするけど、コールバックを必ず実装させなければならないのがちょっと嫌かも。

ApiManager.java(呼ばれる側)

public class ApiManager {
    public interface ApiManagerCallback {
        public void success(Object obj);
        public void failed(Object obj);
    }

    private ApiManagerCallback apiManagerCallback;

    public void setCallbacks(ApiManagerCallback apiManagerCallback) {
        this.apiManagerCallback = apiManagerCallback;
    }

    public void callApi() {
        try {
            apiManagerCallback.success("success");
        } catch (Exception e) {
            apiManagerCallback.failed("failed");
        }
    }
}

MainActivity.java(呼び出す側)

public class MainActivity extends AppCompatActivity implements ApiManager.ApiManagerCallback {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       ApiManager apiManager = new ApiManager();
       apiManager.setCallbacks(this);
       apiManager.callApi();
   }

   public void success(Object obj) {
       // 成功
   }

   public void failed(Object obj) {
       // 失敗
   }
}

実装2

実装1より呼び出す側のコードが少し見辛い気もするけど、失敗時のコールバックが必須でないのがいいかも。

ApiManager.java(呼ばれる側)

public class ApiManager {
    public interface ApiManagerCallback {
       void call(Object obj);
    }

    void connect(final ApiManagerCallback success, final ApiManagerCallback failed) {
        try {
            success.call("success!!");
        } catch (Exception e) {
            if (failed != null) {
                failed.call("failed");
            }
        }
    }
}

MainActivity.java(呼び出す側)

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ApiManager apiManager = new ApiManager();
        apiManager.connect(new ApiManager.ApiManagerCallback() {
            @Override
            public void call(Object obj) {
                // 成功
            }
        }, new ApiManager.ApiManagerCallback() {
            @Override
            public void call(Object obj) {
                // 失敗
            }
        });
    }
}

きっともっといい書き方あるんだろうけど、自分の頭ではこんなものかな。難しい。。。もっといい書き方教えてください。以上です

石の上にも3年

初めて正社員として就職した会社を辞めると伝えたときに上司に言われた言葉。
何があっても3年は続けろって意味だと思うけど当時自分は1年半でその会社を辞めた。

その後あまり長続きすることもなく職場を転々としてきた気がする。適当な理由で退職したが本音は以下だったと記憶している。
1. 家庭の事情 〜1年半在籍(100人規模のSES事業)
2. 会社の新体制が嫌だった 〜5年在籍(70人規模の受託開発会社)
3. 社長が怖すぎた 〜3ヶ月在籍(3人規模の何か)
4. より技術を高められそうな環境で働きたかった 〜2年在籍(20人規模のCP)

今思うと自分の対応次第で辞める必要なかったと思えるものがいくつかある。
結局自分の言いたいことを言わずに勝手にイライラして何も言わずにやめるってパターンが1番もったいなかった気がする。
1と3は今考えても仕方ない。2と4は他にも選択肢があったと思う。

何も言わないことで丸く納めていたつもりでも、それがつもって辞めたら会社にとっては1番不利益。結局コミュニケーション能力ってそこなのかな。。。以上です

PHPから始めるメリット・デメリット

まず自分のポジションとしてはPHPでIT業界で働き始めて10年以上経過。
今もかなりPHPにお世話になっています。

メリット
・直感的にわかりやすい。挫折しずらい
・ネット上にサンプルコードが多いのでやりたいことがすぐ実現できる。
・挫折しずらいので時間をかけてWeb周辺の知識も得られる

デメリット
・アプリ等に手を出した時にPHPよりはるかにネット上での情報が少ないので挫折しやすい。
PHPメインの会社に就職すると全体的に緩いので成長しずらい(気がする)

ビジネス指向というかWebでアイデアを実現したい人には1番いいと思う。
将来的に技術を高めて食べて行きたいならPHPはおすすめできないかな。

ふと思ったので書きました、以上です

【ansible】hello world

はじめに

ずっと前から使おうと思って概要とかは見てたけど実際使ったことはありませんでした。
今回実際に案件で使ってみようと思って実際にいじってみました。

簡単で手軽なのをみんな謳っている感じだったのでまぁつまることもないだろうと思ってたのですが、若干時間かかりました。
で、とりあえず自分のPCからVPSAWSへ実行してみる形を想定して手を動かして見ました。

実際に動かす

Macでの作業で今回はvagrant上のサーバへ実行してみました。
とりあえず最低限知っておいた方がよさそうなキーワードは以下

インベントリファイル
意味的にはhostsファイルみたいな感じ。使用したいサーバーはとりあえずここに書かないとダメ。
自分的には.ssh/configのHostに書いてるものを書くと解釈したらスッキリした。

playbook
手順書みたいなもの。手順書だと実際にコマンドを書くけど、ansibleのモジュール(方言)使って記述する感じ。

以下の.ssh/configの場合の例
.ssh/config

Host vagrant_web
  HostName 192.168.33.10
  Port 22
  User vagrant
  IdentityFile path/to/秘密鍵

vagrantの場合、秘密鍵とかあんまり意識しないけどvagrant ssh-configでIdentityFileで確認できる

hosts(インベントリファイル)

vagrant_web

set_timezone.yml(playbook)

- hosts: vagrant_web
  user: vagrant
  become: true
  tasks:
    - name: set timezone
      command: cp /usr/share/zoneinfo/Japan /etc/localtime
    - name: set timezone
      copy: content='ZONE="Asia/Tokyo"' dest=/etc/sysconfig/clock

実行する

$ ansible-playbook -i ./hosts ./set_timezone.yml

何にはまったのか
いろんなサイト見てたらインベントリファイルは/etc/ansible/hostsに書いてる。けどMacだとそれがなかったから。
実際はオプションiを使えばファイルを指定できる。

ヘルプみるとそもそもデフォルトの場所もosによって違うみたい。

$ ansible -h
-i INVENTORY, --inventory-file=INVENTORY
 specify inventory host path
 (default=/usr/local/etc/ansible/hosts) or comma
 separated host list.

タイトルはhello worldだけどhello world出てこなかった。。。
以上です

【xcode】プロジェクト名を変更するのが思ったより面倒だったので手順まとめておく

はじめに

アプリ名とかを仮のまま開発を進めて途中でアプリ名が決定。
プロジェクト名などが旧名称のままだと気持ち悪いのでプロジェクト名を変更したかったのでその時の手順をまとめておきます。

今回は以下の名前をで変更します。
変更前:SampleOld
変更後:SampleNew

とりあえず動くようにする

プロジェクト名を変更

xcodeの[Identity and Type]から「SampleOld」→「SampleNew」に変更。
赤枠の箇所をすべて修正すればたぶんOK
f:id:yoppy0066:20170121000555p:plain

Cocoapods修正

Podfileにプロジェクト名の記述があるので修正

Podfile

target 'SampleNew' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    use_frameworks!
    # Pods for SampleNew
    pod 'AFNetworking'
    ・・・

    target 'SampleNewTests' do
      inherit! :search_paths
      # Pods for testing
    end

    target 'SampleNewUITests' do
      inherit! :search_paths
      # Pods for testing
    end
end

インストールし直す

$ pod install
Bridging-Header.h修正

まずはリネーム
SampleOld-Bridging-Header.h →Sample New-Bridging-Header.h

設定も修正
f:id:yoppy0066:20170121000710p:plain

ここまででビルドとかは問題なくできるようになった。
しかしプロジェクトの中を見るとわかるが実際のフォルダ名はSampleOldのままで気持ち悪い。

旧プロジェクト名を完全になくす

プロジェクトディレクトリ直下に
SampleOld、SampleOldTests、SampleOldUITestsというフォルダが残っているのでそれぞれSampleOld => SampleNewにリネーム

テキストファイルの文字列を置換
find . -path "./.git" -prune -o -type f -print | perl -nle 'print if -f && -T' | xargs sed -i "" "s/SampleOld/SampleNew/g"
バイナリファイルの文字列を置換

バイナリファイルの置換とかやり方わからなかたったので、数も多くないのでviで直接編集した。

検索

$ find . -path "./.git" -prune -o -type f -print | xargs grep "SampleOld" 2> /dev/null
Binary file ./SampleOld.xcworkspace/xcuserdata/xxx.xcuserdatad/UserInterfaceState.xcuserstate matches
・・・

ファイル編集

$ vi -b ./SampleOld.xcworkspace/xcuserdata/xxx.xcuserdatad/UserInterfaceState.xcuserstate
・・・
:%s/SampleOld/SampleNew/g # 全置換して
:wq! # 保存
missing from working copy

git、svnを使ってる場合、ビルドすると上記のワーニングが出る。
コミットすると消えるらしい

さいごに

とりあえずここまでやったらちゃんと動いてる感じ。
今後何も起きないことを祈ります。以上です

以下、参考にさせて頂きました
findで特定のディレクトリを検索対象外(除外)にする - hogehoge foobar Blog Style5
findでテキストファイルのみ抽出 - Qiita

【android】Fragment + ListViewでのAPIへのリクエストのタイミングについて

はじめに

今回やりたかったことは以下
APIから取得したデータをFragment上のListViewへセット
・ListViewのセルをタップしたら詳細画面へ遷移
・詳細画面で戻るボタンでListViewへ戻る

これだけと思ってたら1日はまってしまった。
何にはまったかというと詳細画面から戻った時にAPIへ再度リクエストしていた。

これの解決策がなかなか出てこなかった。。。
そもそもFragmentのライフサイクルとか全然頭になかったところからスタートだったので色々と知識不足

解決策

http://qiita.com/ymd_aaa/items/d04d174fef98c93ef593
中々みつからなかったがまさにここに求めていた答えがありました。

APIリクエストしてデータの取得してアダプタへのセットをonCreateViewメソッドで行なっていたのですが。
これをonCreateメソッドで行うようにすれば戻ってきた時にデータの再取得は行わずやりたいことができました。

処理イメージ

public class MyFragment extends Fragment {

    private ArrayList<UserData> userDataList;
    private UserDataAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // データの初期化                                                                                                                                                                                  
        userDataList = new ArrayList<>();
        adapter = new MuserDataAdapter(getContext(), 0, userDataList);

        // ★ここでAPIコールしてレスポンスをアダプタにデータをセット                                                                                                                                    
        // adapter.notifyDataSetChanged();とか                                                                                                                                                                 
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_my, container, false);

        // ListViewセット                                                                                                                                                                                          
        ListView listView = (ListView)view.findViewById(R.id.list_view);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                ・・・
            });

        return view;
    }

    public class UserData {
        ・・・
    }

    public class UserDataAdapter extends ArrayAdapter<UserData> {
        ・・・
    }
}

以上です