著者アーカイブ asaba

asaba 著者:asaba

【html5,CSS】Pure.CSSを少しかじる

開発においてhtml5とCSSを使う機会が増えてきたので、この際その周辺の

フレームワークの使い方でも覚えておこうかなと考えております。

今回使うフレームワークはPure.CSSです。

だけどフレームワークと言ってもまず数が多くどれを使ったらいいか迷いがちです。

一般的(html5やJavaScriptを触ったことがある人)にはCSSのフレームワーク

といえばbootStrapが浮かびますが

このpureCSSというフレームワークは、それよりも軽量で機能もごちゃごちゃしていないので

webでのwebでの開発の幅を広げたいというかたやbootStrapを始めたけど使いにくいというかたにはおすすめだなと感じました。

筆者もCSSのフレームワークに触れることはほぼなかったので学習もかねてブログに跡を残していきたいと思います。

 

例えば、なにも手を付けていない状態だと、大きな画像はブラウザを狭めたときに横にスクロールされてしまいページ枠から飛び出してしまいます。

 

 

このままでは一定の大きさで表示することができないので、さっそくPure.CSSで修正してみました。

<head>の中に<link rel=”stylesheet” href=”https://unpkg.com/purecss@1.0.0/build/pure-min.css”>を入れて

<body>に<img src=“apple.jpg” class=“pure-img”>と記述してみましょう。

すると、見事にブラウザの大きさに合わせてリサイズするようになりました!androidやreactで悩んでいたことがこんな簡単に

できるとは正直考えもしなかったです。classにpure-imgを設定するだけで柔軟に対応できるのですごく使い勝手がいいなと

感じました。

 

これで満足してしまいそうでしたが、まだhtmlの基本でもあるフォームを作っていないことを思い出したので

とりあえず公式のサンプルを見ながら書いてみました。

※コードは、公式に似たようなものがあるのでそちらをご覧ください。

各フォームとセレクトボタンを作ってみました。従来のhtmlで作るボタンと比べると角がないというか今どきの

フォームっぽくて安心感がありますね。(某就活サイトとかブログの新規登録ページとかがこんな感じでした。)

これだけでも達成感がでてしまいましたが、更に掘り進んでテキストとかボタンの色を変えてみたいなとか思いついたので

送信ボタンの色を変えてみました。

ほんとにサンプルで書かれたものに数行スパイスを加えた程度のコーディングでしたが、特にこれといって難しい問題は

見つからずにいい意味でさっぱりとしたフォームだと思いました。

この次はinput type = “file”やimgタグをいじってみようかと思います。もしこっちでも使用感がよければ

主要フレームワークとして使っていきたいなと思います。

asaba 著者:asaba

【javaScript】split関数を使って文字列を分割する方法

先週は丸々一週間androidの記事だったので他の話題も振っていきたいと思います。

splitはStringオブジェクトの組み込みメソッドとして用意されており、文字列を任意の箇所で区切って分割することが可能になります。

今回はそのsplit関数を使ってスラッシュで区切られている値を切り分けて取得する方法を書いていきたいと思います。

はじめに、ごくシンプルなコードで説明していきます。

ここでは例として動物の名前をカンマで区切って、それをsplitで分割していきたいと思います。

[javaScript]
var str = 'user-1,user-2,user-3';

//「, (カンマ)」で区切って分割する

var result = str.split(',');

[/javaScript]

console.logで試してみると、resultの中にしっかりと動物ごとに区切られて格納されていることが分かると思います。

[javaScript]
["うさぎ", "ネコ", "タヌキ"]

[/javaScript]

また、分割された文字列は配列のように番号を指定した取り出すことができます。

取り出す方法は受け取ったresult変数で番号を指定するだけ。ここまで取得できれば後は煮るなり焼くなりで好きなように

各値を扱うことができます。

[javaScript]
const rabbit = result[0];
const cat = result[1];
const raccoon = result[2];
[/javaScript]


reactでも同じ形式で使えるので、splitを使ってみたいという方の参考になればと思います。

ここまでのベーシックな使い方を覚えていれば捻った運用などをしなければ困らないかと思われます。

split関数は、Dateで取得した時刻や生年月日をハイフンやスラッシュで区切って切り分けた度分秒や年月日

を利用したい変数に各々入れて使ったりと小回りが利くので、使いこなせるようになると便利ですね。

asaba 著者:asaba

【cordova-react】componentWillReceivePropsが廃止になっていた話

componentWillReceivePropsというライフサイクルメソッドは最新のstateを受け取って更新することができ、前のページで受け取った値を

上書きしてstateに設定することができるメソッドです。

自分はselectタグで何も入力せずに次のページに進む、つまりデフォルトの値を最新の状態で受け取りたかったので

使っていたのですがずいぶん前に廃止するって決められていたみたいです。

Reactはv16まではこれまでのバージョンとほぼ同じ動きをするように決められていたのですが

v17になってからはRender Phaseという実装がrenderする度に何度も呼ばれ、これがループのようにぐるぐる回ってしまうため

危険視されているみたいですね・・・。

 

render部分がループすれば当然コンポーネントでバグがわんさかでて保守性が著しく落ちてしまうので使うのを避けてくださいなので

代わりにcomponentDidUpdateかUNSAFE_componentWillReceivePropsに置き換えてねという記事を見かけたので

後者のUNSAFE_componentWillReceivePropを使うことにしました。

 

どちらもprop・state共にrenderに影響を及ぼすことなくsetStateできるので値を遷移する前に更新したい

もしくは他の関数の影響を受けないように最後にstateの更新をしたいというかたは今使っているcomponentWillReceiveProps

を避けて上のどちらかに切り替えれば安牌なのかなぁと感じました。

※componentDidUpdateでthis.stateすると、無限にstateし続けることを知ったのでUNSAFE_componentWillReceivePropを

使ってください!!

asaba 著者:asaba

【anadroidJava】続・ExifInterfaceで画像の向きを変える

ExifInterface記事の三回目になります。

前回はExifInterfaceクラスを使って画像の向きを取得していたと思いますが、今回はその画像の向き情報を使って

実際に向きを正しい位置に変えて表示するコードを書いてみようと思います。

まず、通常通りメソッドを書きますが、ここでの引数は前回取得した画像の向き情報が入っている変数locatateになります。

<pre>public void replace(int locatate,Bitmap bitmap){
//ここに処理を書きます
}</pre>

二つ目の引数は、このメソッドを叩く前に取得したBitmapのデータになります。

つまり、まだ正しい向きに修正されていない画像が変数に入っている状態ですね。

ここで実際に向きを変える工程に入りますが、まず最初にMatrixクラスをnewします。

画像を動的に編集する手段は枚挙に暇がありませんが、このMatrix拡大・縮小・回転など画像に関するアクションを全て揃えており

androidで画像をいじるときはよく重宝して使っています。

このmatrixを使う前にswitch文を使って角度別に処理を分けていきたいと思います。

case別で90,180,270とありますが、これは前回のORIENTATION_ROTATE_〇〇に合わせて指定した角度に修正するように

制御しており、引数のlocatateが90ならば一番最初のcase90で処理を受けて加工されていきます。

ORIENTATION_ROTATE_〇〇なんてわかりにくいという方も見受けられますが、慣れてくれば「ああこの角度に修正すればいいのね。」

みたいに感覚で慣れてくると思います。

public void replace(int locatate,Bitmap bitmap){
<pre>    int imageWidth = bitmap.getWidth();
    int imageHeight = bitmap.getHeight();
    Bitmap bitmap2;
    // Matrix インスタンス生成
    Matrix matrix = new Matrix();</pre>
<pre>     switch (locatate) {
        case 90:
            matrix.setRotate(90, imageWidth/2, imageHeight/2);
            // 90度回転したBitmap画像を生成
            matrix.postScale(0.3f, 0.3f);// 0.5倍調整
            bitmap2 = Bitmap.createBitmap(bitmap, 0, 0,
                    imageWidth, imageHeight, matrix, true);
            imageView.setImageBitmap(bitmap2);
            break;
        case 180:
            matrix.setRotate(180, imageWidth/2, imageHeight/2);
            // 90度回転したBitmap画像を生成
            matrix.postScale(0.3f, 0.3f);// 0.5倍調整
            bitmap2 = Bitmap.createBitmap(bitmap, 0, 0,
                    imageWidth, imageHeight, matrix, true);
            imageView.setImageBitmap(bitmap2);
            break;
        case 270:
            matrix.setRotate(270, imageWidth/2, imageHeight/2);
            // 90度回転したBitmap画像を生成
            matrix.postScale(0.3f, 0.3f);// 0.5倍調整
            bitmap2 = Bitmap.createBitmap(bitmap, 0, 0,
                    imageWidth, imageHeight, matrix, true);
            imageView.setImageBitmap(bitmap2);
            break;
            default:
                matrix.postScale(0.3f, 0.3f);// 0.5倍調整
                bitmap2 = Bitmap.createBitmap(bitmap, 0, 0,
                        imageWidth, imageHeight, matrix, true);
                imageView.setImageBitmap(bitmap2);
    }
}</pre>
}

三日間ExifInterfaceのお話をしましたがまだまだ作っているアプリにも改善の余地があるのでまた画像周りを

いじることがあれば記事に載せるかもしれません。

あと前にも書きましたが、androidStudioのgradleや実機のスペックが人によって違ってくるのでここで紹介した

設定に合わせる必要は全くないのでそこは皆さんの環境に合わせてください。
 

asaba 著者:asaba

【androidJava】exifInterface:exif情報の取得

前回はexifInterfaceを使うためのgradleの設定をしたので、今回いよいよ実際にコードを書いて説明していきたいと思います。

 

前述のサポートにより、画像を扱うアプリではInputstreamを使うことでExifInterfaceがぐっと使いやすくなりました。

これにより、受け取ったURIから直接画像のexif情報を取得できるようになりました。

exifInterfaceをnewする前にInputStreamを初期化しておきましょう。

<pre>InputStream in = null;</pre>

ここでようやくexifInterfaceクラスを使うことが出来ます。次に向き(orientation)の取得ですが、ここではexifInterfaceクラスの

メソッドgetAttributeIntを使って向きを取得します。getAttributeIntの使い方ですが、取得する情報のタグを指定して値を取得する.

だけで使うことができます。例えば、何の変哲もない修正していない画像を取得する場合はExifInterface.ORIENTATION_NORMALを

指定します。

<pre>int orientation = exifInterface.getAttributeInt(
        ExifInterface.TAG_ORIENTATION,
        ExifInterface.ORIENTATION_NORMAL);</pre>

無事に取得できれば後はこのorientationを変更したい角度に合わせてswitch文にセットすれば対象の画像のexif情報を

取ってくることができますね。

<pre>switch (orientation) {
    case ExifInterface.ORIENTATION_ROTATE_90:
        rotation = 90;
        break;
    case ExifInterface.ORIENTATION_ROTATE_180:
        rotation = 180;
        break;
    case ExifInterface.ORIENTATION_ROTATE_270:
        rotation = 270;
        break;
}</pre>

ExifInterface.ORIENTATION_ROTATE_〇〇はぱっと見分かりづらいですが、ものすごくかみ砕いて「この角度にすれば正しい位置になるよ」

と解釈しておけばその内慣れてくると思います。

次回はこのメソッドで取得したrotation変数を使って実際に向きを変えて表示してみましょう。

断片的なコードだけでは戸惑うかたもいると思うのでメソッド含めた全コードを載せておきます。


public class sample extends AppCompatActivity {

private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
imageView = findViewById(R.id.image_view);
int locatate;
int rotation = 0;
Bitmap bitmap;
Uri uri;
Intent intent = getIntent();
uri = intent.getParcelableExtra("imageUri");
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
//画像の向きを取得
getBmp(uri,rotation);
} catch (IOException e) {
e.printStackTrace();
}
}
public int getBmp(Uri uri,int rotation) {
  InputStream in = null;
  try {
    in = getContentResolver().openInputStream(uri);
    ExifInterface exifInterface = new ExifInterface(in);
    //緯度経度を取得
    getLatlong(exifInterface);
   //画像の向きを取得
    int orientation = exifInterface.getAttributeInt(
    ExifInterface.TAG_ORIENTATION,
    ExifInterface.ORIENTATION_NORMAL);
   switch (orientation) {
     case ExifInterface.ORIENTATION_ROTATE_90:
     rotation = 90;
     break;
     case ExifInterface.ORIENTATION_ROTATE_180:
     rotation = 180;
     break;
     case ExifInterface.ORIENTATION_ROTATE_270:
     rotation = 270;
     break;
  }
    System.out.println(rotation);
  } catch (IOException e) {
    e.printStackTrace();
  } finally {
    if (in != null) {
      try {
        in.close();
      } catch (IOException ignored) {
    }
  }
}
     return rotation;
}
}

 

 

asaba 著者:asaba

【androidJava】exifInterfaceの初期化

長い間exifInterfaceの使い方がおぼろげだったのですが、理解が深まってきたところで小出しで記事をかくことにしました。

今回はチュートリアルみたいな感じでいきなり実践はせず設定の部分だけアウトプットすることにしました。

 

本題ですが、このexifInterfaceというのは1994年に富士フィルムが開発した画像のデータを含んだ形式のことを指します。

このデータを使うことで、角度を修正したりリサイズをしたり写真を撮った位置所法を取得できたりと画像を扱うプログラム

ならほぼ網羅することができます。

 

このExifInterfaceはapiレベルが24以上と推奨されていましたが

Support Library 25.1.0 のリリースに合わせて新たに ExifInterface Support Library が追加されたので、

apiが24以下の端末でも利用できるようになりました。

 

まずはgradleでminSDKVersionが実機より高くないか確認して、高かった場合はその実機のAPIより低くする必要

があります。

例えば、使用している実機のapiが22で、minSdkVersionが24だった場合はこのままでは怒られて使用できないので

minSdkVersionのapiレベルを下げましょう。

 

しかしminSDKVersionが低すぎても警告を受ける場合があるので今実機として使っているandroidのapiレベルが同じになるように

合わせてgradleのminSDKVersionを調整してみてください。

例えば実機のapiレベルが22の場合は


<span style="font-size: 14pt;">minSDKVersion 16 ×</span>

 


<span style="font-size: 14pt;">minSDKVersion 22 〇</span>

 

念のためにぴったりにしておいたほうが間違いないのでw

 

マニフェスト部分にもしっかりとパーミッションを書いておきましょう。

<pre><uses-sdk android:minSdkVersion="22" /></pre>

 

これでexifIterfaceを使う下準備は終わりました。次回は実際にexifInterfaceを使って向きを取得してみましょう。

 

 

 

 

asaba 著者:asaba

【androidJava】カメラ・ギャラリーを同じダイアログに入れて選択させる方法

javascriptでできなかったカメラとギャラリーが同じダイアログに入った機能があっさりできてしまいました。

この場合はコードを先にみてしまった方が早いと思うので端折ります。

//一番最初にカメラ・ギャラりーを識別するための定数を記述しておく
private static final int REQUEST_CHOOSER = 1000;
private void showGallery() {

    //カメラの起動Intentの用意
    String photoName = System.currentTimeMillis() + ".jpg";
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.Images.Media.TITLE, photoName);
    contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    m_uri = getContentResolver()
            .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);

    Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (intentCamera.resolveActivity(getPackageManager()) != null) {
        // Create the File where the photo should go
        File photoFile = null;
        try {
            photoFile = createImageFile();
            System.out.println(photoFile);
        } catch (IOException ex) {
            // Error occurred while creating the File
            Log.d("Error", ex.getMessage());
            Toast.makeText(getBaseContext(), ex.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }
    // ギャラリー用のIntent作成
    Intent intentGallery;
    if (Build.VERSION.SDK_INT &amp;amp;amp;lt; 19) {
        intentGallery = new Intent(Intent.ACTION_GET_CONTENT);
        intentGallery.setType("image/*");
    } else {
        intentGallery = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intentGallery.addCategory(Intent.CATEGORY_OPENABLE);
        intentGallery.setType("image/jpeg");
    }
    Intent intent = Intent.createChooser(intentCamera, "画像の選択");
    intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {intentGallery});
    startActivityForResult(intent, REQUEST_CHOOSER);
}
</pre>
<pre>private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "PNG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".png",         /* suffix */
            storageDir      /* directory */
    );
    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = Uri.parse(image.getAbsolutePath());
    return image;
}</pre>
<pre>

カメラ・ギャラリーから取得した画像をonActivityResultで受け取って処理をします。

 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode == REQUEST_CHOOSER) {
  //ここに書きたい処理を書く</pre>
<pre>  resultUri = (data != null ? data.getData() : m_uri);</pre>
<pre>  } 
} 

二番目の引数と定数REQUEST_CHOOSERが同じ値なので、if内に処理をしていきます。

上記の例のようにgetDataでuriを取得をすればもうご自由にuriを使うことが出来ますね。

asaba 著者:asaba

【cordova-react】またRが定義されていない・・・

androidのネタになります。

 

いつもどおりtextViewとimageViewをxmlに追加してアクティビティにもオブジェクトを追加してビルドしたのですが

またCannot resolve symbol Rに呼び止められてしまいました(怒)

 

いつもどおりゴミが溜まったのかと思いクリーンビルドしてみたのですが今度はそれが原因ではないみたいです。

ならばと思い範囲を広げてRebuild projectを実行。ログでサクセスが出てきたので今度こそ

治ったかと思ったらまたCannot resolve symbol R・・・失敗しました。

 

先人の知識を借りて画面左下のbuild Valiantsを押してデバッグモードからリリースモードに変更して

再度ビルドしてみても結果は変わらず。

 

やっぱり定義先に問題があるかと思い再度xmlのページにいって再調査。

そういえばimageViewは前のプロジェクトからそのままコピペしたな~もしかしたらこのxmlで使っていない

属性が定義されていてそれが悪さしてるのかと思いそこを重点的に探しました。

 

すると、使っていないっぽい属性を発見。

<ImageView
android:id=”@+id/image_view”
android:scaleType=”center”
android:contentDescription=”@string/description”←こいつだ!
android:layout_margin=”10dp”
android:layout_width=”match_parent”
android:layout_height=”wrap_content” />

 

前のプロジェクトでstring.xmlでボタンの名前などを定義するときに使っていたcontentDescription。

 

こいつはこのプロジェクトでは使っていなかったので迷わず削除して再ビルド。

すると見事にビルドが成功、エラーの原因を突き止めることができました。

 

前のプロジェクトから似たようなコードをコピペするときは使っていないメソッドや属性を確認してから

組み込みましょう。ということを再実感しました。

 

とりあえず同じエラーが起きることのないようリファクタリングを厳しくしましょう。

asaba 著者:asaba

【androidJava】intentでbitmapを遷移させる方法

androidではintent機能を必ずといっていいほど使います。

値を遷移させたりカメラで撮影画面に映ったりなど様々な場面で使うことが出来ます。

今回は画像をintentに持たせて遷移先でやり取りをしたかったのですが!!! FAILED BINDER TRANSACTION !!!というエラーに

ひっかかり見事に怒られてしまいました。

 

どうやらiphoneやandroidで撮影した写真や画像は加工せずに送ると重すぎるためにファイルとして扱うには不適切と見なされ

拒否されてしまうみたいです・・・。

 

少しまわりくどいですが、uriでintentに持たせbitmapに加工するという手段に落ち着きました。

とりあえず遷移先でuriを宣言していればどれだけ重い画像でも持ってこれるので同じような内容でハマっている

方は試してみてください。

 

最後にコードを掲示しておきます。

 

遷移前

<pre>Intent intent = new Intent(this, EditActivity.class);
intent.putExtra("imageUri", uri);
startActivity(intent);</pre>

 

遷移先

<pre>public void getBmp(){
    Intent intent = getIntent();
    Uri uri = intent.getParcelableExtra("imageUri");
    System.out.println(uri);
    try {
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
        imageView.setImageBitmap(bitmap);
    } catch (IOException e) {
        e.printStackTrace();
    }
}</pre>

 

遷移先で変数uriに“imageUri”キーを持つ値を持ってきています。

tryの中ではMediaStoreに問い合わせてuriをBitmapに変換しているところです。(ざっくりですみません)

 

asaba 著者:asaba

【cordova-react】長ったるいコードをfor文で解決させた話

前に書いた記事の後付けです。

selectタグを用いて生年月日をプルダウンする機能を実装したのですが、生年月日を全部手書きで書いたためか

エディタの機能やコーディングのスピードが著しく落ち、メンテナンスしにくいコードになってしまいました。

行を無駄に使っているのでスクロールするときもぎこちなくこの状態では効率が悪いと思い、とりあえず

生年月日をループさせてコードの行を減らすことに努めました。

生年月日のデータをreactで書くとこんな感じになります。悪い例 

 

<pre>    this.dayData = [
      {value: '', label: '▼日にち選択'},
      {value: 1, label: '1'},
      {value: 2, label: '2'},
      {value: 3, label: '3'},
      {value: 4, label: '4'},
      {value: 5, label: '5'},
                .
                .
                .</pre>

 

コンストラクタ内でthis.dayDataを初期化しています。

生年月日なので、19××~20××と幅広い西暦を設定しなければいけません。

当然これを直接書くと年齢の幅を考えると100行近くなってしまいますね・・・。

 

短いですがここでシェイプアップのためにrender()内で記述したコードを説明します。

 

//コンストラクタ内

  {value: '', label: '▼日にち選択'},


  //render内
    for(var dayNum = 1930; dayNum <=2030; dayNum++){
    this.dayData[dayNum] = {value: dayNum, label: dayNum};
    }

 

みてくれは通常のjavascriptで連想配列を新しく追加するときのような形式になっています。

これを書いたら後はmapで上のデータを基に新しく配列をつくれば完成です。