ラベル Android の投稿を表示しています。 すべての投稿を表示
ラベル Android の投稿を表示しています。 すべての投稿を表示

2018年2月24日土曜日

【Android】ViewPager

  • 公開日:2018年02月23日

記事概要

java-programming向けの詳細な記事を書く時間が取れないので、ざっくりとこちらに情報を載せます。
ViewPagerアニメーションの学習と研究をしていたので、そのまとめ記事です。

環境

  • Android Studio 3.0.1

概要

ViewPagerはよく使いますが、きちんと内部コードを追って学習したことはほとんどありませんでした。
記事の内容は、この公式ドキュメントがベースです。さらに深掘りしています。

ViewPagerとPageTransformer

ViewPagerのアニメーション方法を変更するには、ViewPager.PageTransformerを使います。ViewPager.PageTransformerはtransformPageが宣言されているInterfaceです。

ViewPager.java

    public interface PageTransformer {
        /**
         * Apply a property transformation to the given page.
         *
         * @param page Apply the transformation to this page
         * @param position Position of page relative to the current front-and-center
         *                 position of the pager. 0 is front and center. 1 is one full
         *                 page position to the right, and -1 is one page position to the left.
         */
        void transformPage(@NonNull View page, float position);
    }

画面切り替え時にtransformPageメソッドが呼び出されます。

PageTransformerで実装した内容を有効にするには、setPageTransformerメソッドを使います。

ViewPager.java

mPager.setPageTransformer(true, new SamplePageTransformer());

上記のように設定すると、実装した具体的なPageTransformerクラスがmPageTransformer変数に設定され、onPageScrolledメソッドで呼び出されます。

ViewPager.java

        if (mPageTransformer != null) {
            final int scrollX = getScrollX();
            final int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                final View child = getChildAt(i);
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();

                if (lp.isDecor) continue;
                final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
                mPageTransformer.transformPage(child, transformPos);
            }
        }

PageTransformerクラスの実装

具体的なPageTransformerクラスは、PageTransformerをimplementsして実装します。サンプルとしてZoomOutPageTransformerクラスを実装してみます。

{project_folder}/ZoomOutPageTransformer.java

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.85f;
    private static final float MIN_ALPHA = 0.5f;

    @Override
    public void transformPage(@NonNull View page, float position) {
        int pageWidth = page.getWidth();
        int pageHeight = page.getHeight();

        Log.d("ZoomOutPage", "position :" + position + ", view id : " + page.getId());
        Log.d("ZoomOutPage", "pageWidth :" + pageWidth + ", view id : " + page.getId());
        Log.d("ZoomOutPage", "pageWidth :" + pageHeight + ", view id : " + page.getId());

        if (position  < -1) {
            // 透明にする
            page.setAlpha(0.0f);
        } else if (position <= 1) {
            // -1 < posiiton < 1
            // 多分、徐々に小さくするため
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            // margin 黒枠のところ
            // 縦 top bottomやな
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            // 水平 名前が left rightだと
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
//            if (position < 0) {
//                // 相対的に動かす。これが無いと画像が動かないのでおかしくなるはず。
//                page.setTranslationX(horzMargin - vertMargin / 2);
//            } else {
//                page.setTranslationX(-horzMargin + vertMargin / 2);
//            }

            // Scale the page down (between MIN_SCALE and 1)
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            page.setAlpha(MIN_ALPHA +
                    (scaleFactor - MIN_SCALE) /
                            (1 - MIN_SCALE) * (1 - MIN_ALPHA));

        } else {
            // 透明にする
            page.setAlpha(0.0f);
        }


    }
}

positionはページ数でなく、引数のページの相対的な位置です。-1 < x < 1までの範囲の値をとり、0が中央, -1が左, 1が右となります。

vertMarginとhorzMarginはページ切り替え時に、ページ間のviewの距離を詰めるための計算に使っています。setTranslationXでviewの位置をずらすことで、ページ移動のアニメーションをスムーズに見せています。名称がわかりにくいので、topBottomMarginとleftRightMarginで実装した方がわかりやすいと思います。

続いて、DepthPageTransformerを実装してみます。

{project_folder}/DepthPageTransformer.java

public class DepthPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.75f;
    @Override
    public void transformPage(@NonNull View page, float position) {
        int pageWidth = page.getWidth();

        if (position < -1) {
            // 透明にする
            page.setAlpha(0.0f);
        } else if (position <= 0) {
            // [-1 : 0]
            // Use the default slide transition when moving to the left page
            page.setAlpha(1);
            page.setTranslationX(0);
            page.setScaleX(1);
            page.setScaleY(1);

        } else if (position <= 1) {
            // [0 : 1]
            // Fade the page out.
            page.setAlpha(1 - position);

            // Counteract the default slide transition
            page.setTranslationX(pageWidth * -position);

            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
        } else {
            // 透明にする
            page.setAlpha(0.0f);
        }
    }
}

こちらの方が理解しやすですね。左と右で綺麗に処理が分割されています。position <= 0, つまり左側はただスライドするだけです。

page.setAlphaで透過状態を管理しています。徐々に薄くなったり、濃くなったりしています。
ズームも同じで、大から小, 小から大へとviewを変化させています。setScaleX, setScaleYで拡大縮小をしています。

page.setTranslationX(pageWidth * -position);で画面が停止しているように見えるようにしています。

結論

ViewPager.PageTransformerを使うことで、アニメーションを実装できます。色々とやってみようと思います。

PICK UP

運営サイト


参考


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2017年11月19日日曜日

【Android Studio 3.0】既存アプリをAndroid Studio 3.0に対応させる。

  • 公開日:2017年11月18日

記事概要

kotlinとJavaの混じったアプリを2.3.x系でビルドすると、制約がひどく、ビルドも遅いのでAndroid Studio 3.0に移行しました.
結構色々なエラーと修正が発生したので、今後移行する人の役に立つように作業メモを記載して残しておきます。

環境

  • Android Studio 2.3.1 → Android Studio 3.0

Android Studio 3.0に対応

ダイアログで表示されるgradleのversionにアップデートします。ダイアログでOKを押下します。
自動的にbuild.gradleと/gradle/wrapper/gradle-wrapper.propertiesが上書きされます。

{project_folder}/build.gradle

     dependencies {
-        classpath 'com.android.tools.build:gradle:2.3.3'
+        classpath 'com.android.tools.build:gradle:3.0.0'
         classpath 'com.google.gms:google-services:3.0.0'
     }

{project_folder}/gradle/wrapper/gradle-wrapper.properties

-#Fri Jul 28 22:16:36 JST 2017
+#Sat Nov 18 19:40:49 JST 2017
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

jackOptionsを無効化

gradleの変更だけだと、おそらくビルドに失敗します。jackOptionsが有効だと以下のエラーが出力されます。

Event Log

Warning:The Jack toolchain is deprecated and will not run. To enable support for Java 8 language features built into the plugin, remove 'jackOptions { ... }' from your build.gradle file, and add

android.compileOptions.sourceCompatibility 1.8
android.compileOptions.targetCompatibility 1.8

Future versions of the plugin will not support usage of 'jackOptions' in build.gradle.
To learn more, go to https://d.android.com/r/tools/java-8-support-message.html

エラーの内容は、jackOptionsはもうすぐサポート終わるから使わないでってことです。
なので、以下のように変更します。

{project_folder}/app/build.gradle

    defaultConfig {
         // something...
         vectorDrawables.useSupportLibrary = true
-        jackOptions {
-            enabled true
-        }
         multiDexEnabled true
         // something...
    }

jackOptionsを削除するだけです。sourceCompatibilityとtargetCompatibilityは残しておきます。

flavor dimensionsの設定

Android Studio 3.0からは、単一のflavor dimensionを使用する場合でも、すべてのflavorが名前付きflavor dimensionに属している必要があります。でないと、以下のようなエラーが発生します。

Event Log

All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html

つまり、dimensionを定義してね。ってことです。正直、ダメな仕様だと思います。大規模なプロジェクトには便利な機能ですが、必須である理由がわかりません。大抵のアプリは小さいアプリなはずです。いずれ元に戻ると思いたいですね。
ビルド周りは大きく変わっているので、面倒でもサンプルプロジェクトを作成して仕様を確認することをお勧めします。ドキュメントを読むだけだと、ピンと来ないと思います。

私の環境は分ける必要がないので、以下のように名前を一つ追加しただけです。

{project_folder}/app/build.gradle

+    flavorDimensions 'normal'
     productFlavors {
         dev {
+            dimension 'normal'
         }
         prod {
+            dimension 'normal'
         }
     }

kotlinのバージョンアップ

jackOptionsが不要になったので、kotlinのバージョン縛りがなくなりました。なので、このままだと以下のエラーが発生します。

Event Log

Unable to find method 'com.android.build.gradle.internal.variant.BaseVariantData.getOutputs()Ljava/util/List;'. Possible causes for this unexpected error include:
Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network)
The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart)
Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.
In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

エラーにkotlinの文字が出ないのは良くないですね。いずれは改善して欲しいですね。
kotlinのアップデートはgradleの記載を変更するだけです。

{project_folder}/app/build.gradle

 buildscript {
     ext {
-        kotlin_version = '1.1.1'
+        kotlin_version = '1.1.51'
     }

buildToolのバージョンアップ

buildToolも更新が必要です。buildToolのバージョンが古いと以下の警告メッセージが表示されます。

Event Log

Error:The specified Android SDK Build Tools version (26.0.1) is ignored, as it is below the minimum supported version (26.0.2) for Android Gradle Plugin 3.0.0.
Android SDK Build Tools 26.0.2 will be used.
To suppress this warning, remove "buildToolsVersion '26.0.1'" from your build.gradle file, as each version of the Android Gradle Plugin now has a default version of the build tools.

gradleを更新します。

{project_folder}/app/build.gradle

 android {
-    compileSdkVersion 26
+    compileSdkVersion 27
     buildToolsVersion rootProject.buildToolsVersion

{project_folder}/build.gradle

 allprojects {
     repositories {
+        google()
         mavenCentral()
-        maven { url 'https://maven.google.com' }
     }
 }

 ext {
-    buildToolsVersion = "26.0.1"
-    supportLibVersion = "26.1.0"
+    buildToolsVersion = "27.0.1"
+    supportLibVersion = "27.0.1"
     multidexVersion = "1.0.0"
-    constraintLayoutVersion = "1.0.2"
+    constraintLayoutVersion = "1.1.0-beta3"
     rxandroidVersion = "2.0.1"
     rxjavaVersion = "2.1.3"

maven { url 'https://maven.google.com' } を google() に書き換えできるようになりました。

また、Android Studio 3.0だと、constraintLayoutが安定してIDEで表示されるようになりました。ConstraintLayoutを使うとviewの入れ子を少なくできて、描写が高速になるので、積極的に利用していきましょう。beta版が嫌な人は1.0.2でも良いと思います。サポートライブラリArchitecture Componentsの更新も忘れずに。

コード修正

最後にkotlinのアップデートとsdk27のアップデートのコード対応を行います。
私の環境で発生したエラーと修正方法を記載しておきます。

Error: style attribute '@android:attr/windowEnterAnimation' not found.

@が不要になりました。

{project_folder}/app/src/main/res/values/styles.xml

     <style name="Animations.GrowFromBottom">
-        <item name="@android:windowEnterAnimation">@anim/grow_from_bottom</item>
-        <item name="@android:windowExitAnimation">@anim/shrink_from_top</item>
+        <item name="android:windowEnterAnimation">@anim/grow_from_bottom</item>
+        <item name="android:windowExitAnimation">@anim/shrink_from_top</item>
     </style>
 
     <style name="Animations.GrowFromTop">
-        <item name="@android:windowEnterAnimation">@anim/grow_from_top</item>
-        <item name="@android:windowExitAnimation">@anim/shrink_from_bottom</item>
+        <item name="android:windowEnterAnimation">@anim/grow_from_top</item>
+        <item name="android:windowExitAnimation">@anim/shrink_from_bottom</item>
     </style>
 
     <style name="Animations.PopDownMenu">
-        <item name="@android:windowEnterAnimation">@anim/grow_from_topleft_to_bottomright</item>
-        <item name="@android:windowExitAnimation">@anim/shrink_from_bottomright_to_topleft</item>
+        <item name="android:windowEnterAnimation">@anim/grow_from_topleft_to_bottomright</item>
+        <item name="android:windowExitAnimation">@anim/shrink_from_bottomright_to_topleft</item>
     </style>

Android3.0からは、デフォルトでAAPT2が有効になったことの影響です。

Error: Smart cast to 'Bundle' is impossible, because 'arguments' is a mutable property that could have been changed by this time

getArguments()のSmart castができなくなりました。コードを見ると、sdk27(サポートライブラリ)では以下のように実装されています。

android.support.v4.app.Fragment

    /**
     * Return the arguments supplied when the fragment was instantiated,
     * if any.
     */
    @Nullable
    final public Bundle getArguments() {
        return mArguments;
    }

sdk26(26.1.0)では以下のような実装でした。

android.support.v4.app.Fragment

    /**
     * Return the arguments supplied when the fragment was instantiated,
     * if any.
     */
    final public Bundle getArguments() {
        return mArguments;
    }

@Nullableが追加されています。ブロックの引数を指定する必要があります。

{project_folder}/MainActivity.java

-        arguments?.let {
+        arguments?.let { it ->


というかこれは既存コードに潜在的なバグが含まれていたっぽいです。。。letのブロック内の変数はなるべくitに置き換えるか、名称を変更するべきですね。

Error: Class 'XYZPagerAdapter' is not abstract and does not implement abstract base class member public abstract fun isViewFromObject(@NonNull p0: View, @NonNull p1: Any): Boolean defined in android.support.v4.view.PagerAdapter

PagerAdapterにも変更が入ったようです。コードを見ると、sdk27(サポートライブラリ)では以下のように実装されています。

android.support.v4.app.Fragment

    public abstract boolean isViewFromObject(@NonNull View view, @NonNull Object object);

sdk26(26.1.0)では以下のような実装でした。

android.support.v4.app.Fragment

    public abstract boolean isViewFromObject(View view, Object object);

これも同じように@Nullableが追加されています。?を削除します。

{project_folder}/MainActivity.java

-        override fun isViewFromObject(view: View?, `object`: Any?): Boolean {
+        override fun isViewFromObject(view: View, obj: Any): Boolean {

isViewFromObjectの引数って@NonNullだったんですね。チェックしてコード書いてた時期があったような。

Error: Fragment

Fragmentも変更されてますね。これもsdk27で@Nullableのアノテーションが追加されたのではないでしょうか。

android.support.v4.app.Fragment

    @Nullable
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        return null;
    }

sdk26(26.1.0)では以下のような実装でした。

android.support.v4.app.Fragment

    @Nullable
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        return null;
    }

LayoutInflaterが@NonNullになっています。これは良い修正ですね。以下のように修正します。

{project_folder}/MainActivity.java

-    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,

-        val view = inflater!!.inflate(R.layout.fragment_floating_action, container, false)
+        val view = inflater.inflate(R.layout.fragment_floating_action, container, false)

Error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type FragmentActivity?

FragmentActivityも変更されてますね。これも@Nullableのアノテーションが追加されたのではないでしょうか。

android.support.v4.app.Fragment

    final public FragmentActivity getActivity() {
        return mHost == null ? null : (FragmentActivity) mHost.getActivity();
    }

    public Context getContext() {
        return mHost == null ? null : mHost.getContext();
    }

sdk26(26.1.0)では以下のような実装でした。

android.support.v4.app.Fragment

    @Nullable
    final public FragmentActivity getActivity() {
        return mHost == null ? null : (FragmentActivity) mHost.getActivity();
    }

    /**
     * Return the {@link Context} this fragment is currently associated with.
     */
    @Nullable
    public Context getContext() {
        return mHost == null ? null : mHost.getContext();
    }

Safe-call演算子を使って書き換えます。

色々

-            activity.supportFragmentManager.popBackStack()
+            activity?.supportFragmentManager?.popBackStack()

-            Toast.makeText(context, context.getString(R.string.sample), Toast.LENGTH_SHORT).show()
+            Toast.makeText(context, context?.getString(R.string.sample), Toast.LENGTH_SHORT).show()

gradle修正

gradleを変更します。

compileをimplementationに変更します。

implementationにするとビルドが早くなります。
なぜなら、implementationは、コンパイルする必要がある依存ライブラリだけをコンパイルします。

{project_folder}/build.gradle

-    compile 'com.android.support:multidex:' + rootProject.multidexVersion
-    compile 'com.android.support:appcompat-v7:' + rootProject.supportLibVersion
-    compile 'com.android.support:design:' + rootProject.supportLibVersion
-    compile 'com.android.support:support-v4:' + rootProject.supportLibVersion
-    compile 'com.android.support.constraint:constraint-layout:' + rootProject.constraintLayoutVersion
-    compile 'com.android.support:recyclerview-v7:' + rootProject.supportLibVersion
-    compile 'com.android.support:cardview-v7:' + rootProject.supportLibVersion
+    implementation 'com.android.support:multidex:' + rootProject.multidexVersion
+    implementation 'com.android.support:appcompat-v7:' + rootProject.supportLibVersion
+    implementation 'com.android.support:design:' + rootProject.supportLibVersion
+    implementation 'com.android.support:support-v4:' + rootProject.supportLibVersion
+    implementation 'com.android.support.constraint:constraint-layout:' + rootProject.constraintLayoutVersion
+    implementation 'com.android.support:recyclerview-v7:' + rootProject.supportLibVersion
+    implementation 'com.android.support:cardview-v7:' + rootProject.supportLibVersion

以上で終了です。お疲れさまでした。
コンパイルが随分と高速化されました。

結論

kotlinのNull Safety機能は強力ですね。小さいアプリだとAndroid Architecture Componentsは不要ですね。導入すると無駄にコードも増えますし。

kotlinの導入とconstraintLayoutの導入は本当にお勧めです。8.1のリリースも近いので、そろそろ既存アプリのandroid studio3.0の対応は終了させておきたいですね。

PICK UP

運営サイト


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2017年11月13日月曜日

【書評】Kotlinイン・アクション

  • 公開日:2017年11月13日
  • 最終更新日:2017年11月29日
  • 学習期間:2017年11月06日 - 途中
  • 学習期間:705minites[途中]

初めに

本格的にkotlinを利用するようになってきたので、詳細な仕様を把握するために本書を購入しました。
この記事は感想とまとめを兼ねています。

本の評価には色々な視点がありますが、私はjavaのサーバーサイド、android, kotlinの開発経験があるので、その視点で本書を評価しています。

また、まとめの量が多くなってきたので、更新しながら感想を書いていきます。つまり、途中の殴り書きです。。。
良書だし、ちゃんと最後にまとめます。

紙 or 電子書籍

頻繁に持ち運ぶなら電子書籍。職場や家置いとくなら紙で良いと思います。私はkindleで買いました。kindleだと容量を70Mくらい使うので、空容量に注意しましょう。

本書の対象者

Javaの実装経験と、簡単なkotlinの実装経験がある人が読む本です。javaやkotlinの実装経験がない人が読む本ではありません。

kotlinの実装経験がない場合は、「Kotlinスタートブック」から読みましょう。

章別感想とまとめ

後々開発や復習で見返すようためのメモ書き。気になった事項の調査等。結構無駄に深く読み込んでいる箇所もあるので、そこは無視してください。

1章

kotlinは実用主義。アイデアを探求する言語ではない。
多重配列が使いにくいのはそれでかな?
もしくは、 Effective Javaの項目25「 配列よりリストを好む 」が適用されているか。。。

2章

if文(p23 - p24)

ifは式なので、値を返す

ブロック本体と式本体で記述可能

{project_folder}/inaction/If.kt

fun max (a : Int = 0, b : Int = 0) : Int {
  return if a > b : a ? b
}

{}で囲むことを「ブロック本体を持つ」という。
return文が必要。

式本体だけで書く

{project_folder}/inaction/If.kt

fun max (a : Int = 0, b : Int = 0) : Int = if a > b : a ? b

直接返す場合は「式本体を持つ」という。

式本体の関数の場合は、戻り値も省略可能

{project_folder}/inaction/If.kt

fun max (a : Int = 0, b : Int = 0) = if a > b : a ? b

変数

なるべくval(イミュータブル(不変))で宣言するべき。

クラス

valはイミュータブル(不変)なのでgetterのみ

varはミュータブル(可変)なのでgetterとsetterの両方作成

プロパティを呼び出すとき、実際はgetterを利用している。

greteな仕様だ。

カスタムアクセサ

使ったことない。p33

enum

私は、Android開発ではenumは使わないで、Support Annotationを使う派です。でも、Android Architecture Componentsでは普通に使われていますね。Lifecycleのpublic enum Stateとか。。。proguardで難読化すれば問題はないのですが。。。

Androidの神と呼ばれているJakeWhartonさんはenum使うべき派だそうです。参考
理由は、我々は組み込みエンジニアではなく、Webエンジニアである。との理由だそうです。AndroidエンジニアはWebエンジニアではなく、組み込みエンジニアであるじゃないのかな???よくわかりません。。。

when

whenは式なので値を返す。当然、ブロックを使うこともできます。
javaと異なり、オブジェクトも利用可能。本書では、setOfでSetオブジェクトを作成して比較している。

setOfはkotlinで以下のように実装されている。

{project_folder}/inaction/If.java

public fun <T> setOf(vararg elements: T): Set<T> = if (elements.size > 0) elements.toSet() else emptySet()

Setオブジェクトを返していますね。toSetはkotlin.collectionsパッケージで実装されています。

{project_folder}/inaction/If.java

/**
 * Returns a [Set] of all elements.
 *
 * The returned set preserves the element iteration order of the original array.
 */
public fun <T> Array<out T>.toSet(): Set<T> {
  return when (size) {
  0 -> emptySet()
  1 -> setOf(this[0])
  else -> toCollection(LinkedHashSet<T>(mapCapacity(size)))
  }
}

ここでもwhenを使ってますね。out Tのout 修飾子を利用しています。分散アノテーションともいいます。つまりクラスC は T の プロデューサ であり、 T の コンシューマ ではない、と考えます。

スマートキャスト

kotlinの地雷ですね、これ。ネットにもあまり良い説明が載ってない。どうしても好きになれない仕様。

isでチェックとキャストを両方やる。

valで宣言されている必要がある。

3章

トップレベル関数(p64 - 66)

説明がわかりにくいです。要は、javaのようにクラス宣言をしなくてもメソッドを作成できるし、呼び出せるってことですね。

まずはjavaで乗数を計算するクラスと実行クラスを実装してみます。

{project_folder}/inaction/Top.java

package inaction;

public class Top {
    public static Double topFunction() {
        double  a = 2.0;
        return Math.pow(a, 2.0);
    }
}

{project_folder}/Jikko.java

import inaction.Top;

public class Jikko {
    public static void main(String []args) {
        System.out.println(Top.topFunction());
    }
}

実行結果は[4]です。両方ともclassを宣言して、メソッドにstatic宣言をしています。
kotlinの場合は、classとstatic宣言が不要になります。

{project_folder}/Jikko.kt

import inaction.topFunction

fun main(args : Array) {
    System.out.println(topFunction())
}

{project_folder}/inaction/Top.java

package inaction

fun topFunction() : Int {
    val a = 2.0
    return Math.pow(a, 2.0).toInt()
}

結果は同じように4になります。javaクラスにコンパイルされる時に勝手にクラスが作成されて、メソッドがstaticになります。
さらに、ファイルクラスの名前も変更できます。

{project_folder}/inaction/Top.java

@file:JvmName("AnotherTop")
package inaction

fun topFunction() : Int {
    val a = 2.0
    return Math.pow(a, 2.0).toInt()
}


@file:JvmNameアノテーションでファイル名を変更できます。

呼び出してみます。

{project_folder}/inaction/Top.java

import inaction.AnotherTop;

public class Jikko {
    public static void main(String []args) {
        System.out.println(AnotherTop.topFunction());
    }
}

別名AnotherTopで呼び出せています。

拡張関数

これはkotlinを使っている人はみんな知っていますね。

拡張関数はオーバーライドは無理なことを覚えておきましょう。静的関数だから、当たり前ですね。

可変長引数

使うケースは、まずない気がしますが、忘備録的に記載しておきます。

{project_folder}/inaction/Kahen.kt

fun main(args : Array<String>) {
    accept("test1",  "test2", "test3")
}

fun accept(vararg msg: String) {
    System.out.println(listOf(*msg))
}

可変長引数は、スプレッド演算子「*」を使います。

to

mapOfで利用するtoは関数です。中置呼び出しと呼びます。toはPairクラスを返します。ScalaのTupleと同じ機能です。

{project_folder}/inaction/To.kt

    val map = mapOf(1 to "one", 2 to "two")
    for ((key, value) in map.iterator().withIndex()) {
        System.out.println("key:${key}, valu:${value}")
    }

key:0, valu:1=one
key:1, valu:2=two

トリプルクヴォート

あまり使い道がなさそう

ローカル関数

関数の中で関数の宣言をすることです。javaScriptのような記載が可能です。無駄な宣言を減らせます。

4章

kotlinのクラスやメソッドはデフォルトでfinal。継承可能なクラスはopenをつける必要がある。

{project_folder}/inaction/test.kt

class Button {
    fun disable() {}
    open fun amimate() {}
    fun click() {}
}

// finalエラーが出る。
class TextButton : Button() {

}

openを追加します。

{project_folder}/inaction/test.kt

open class Button {
    fun disable() {}
    open fun amimate() {}
    fun click() {}
}

class TextButton : Button() {
    override fun amimate() {
        super.amimate()
    }

    // これはfinalエラー
    override fun click() {}
    
}

デフォルトがfinalの利点は、スマートキャストが可能になることです。

ただし、abstractクラスのメソッドは継承前提なので、openは不要。

sealed class

暗黙的にopenのついているクラス。クラスの継承を制限するために使います。インタフェースにはsealedがつけられません。子クラスにdataクラスを持つこともできます。
whenでelse文で使うとelseが必要なくなります。まだあまり使い道が理解できてません。

クラス移譲 byキーワード

説明がわかりにくいです。記載してあるコードも動かないし。移譲に関しては、公式サイトを読みましょう。クラス移譲は、インターフェースの実装を他のクラスに委譲できます。
デザインパターンのデリゲートパターンですね。

{project_folder}/inaction/test.kt

interface Base {
    fun onClick()
}

class BaseImpl() : Base {
    override fun onClick() {
        System.out.println("clicked!!")
    }
}

class Application(base: Base) : Base by base

fun main(args: Array) {
    val b = Application(BaseImpl())
    Application(b).onClick()
}

オブジェクト宣言

シングルトンを作成する

5章

コレクション操作

mapは集約

filterはフィルタリング

遅延コレクション操作

一時オブジェクトを生成しないコレクションチェーンです。

mapは集約

SAM

関数が一つのjava interfaceはラムダで代用できる。

匿名objectでも代用できるが、呼び出しごとにインスタンスを生成する。

インスタンスを何度も生成しないで利用する場合は、以下のように実装する(p168)

{project_folder}/inaction/test.kt

vae listener = OnClickListener { view - >
  // something

}

ラムダ内でthisは使えない。なぜならコードブロックだから。

with

最初の引数を、二番目の引数のラムダレシーバに変換する。

{project_folder}/inaction/test.kt

fun alphabet = with(StirngBuilder()) {
  // something
toString
}

上記のような書き方も可能。。。

ラムダの実行結果を返す。
レシーバ(引数)を返したい場合は、applyを使う

apply

レシーバ(引数)を返したい場合に使う。TextViewで複数の値を設定する場合に利用する。(p172)

6章

エルビス演算子

監獄ロックだろ。知ってるよ。

null値の代わりにデフォルトを返す演算子です。

{project_folder}/inaction/test.kt

fun alphabet = with(aaa :Stvring?) {
  val msg: String? = aaa ?: "hello"
}

as?

null値の代わりにデフォルトを返す演算子です。

let

型のチェック

{project_folder}/inaction/test.kt

if (aaa != null) {
  mesoddo(aaa)
}

{project_folder}/inaction/test.kt

aaa?.let { mesoddo(it)}

関連記事

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2017年5月27日土曜日

【Android7.1】Architecture componentsの調査。AppCompatActivityでLifecycleを利用する

  • 公開日:2017年05月27日

記事概要

Google I/O 2017でandroid-architecture-componentsが発表されました。
なかなか良さそうなライブラリだったので、導入して動かしてみました。

この記事は、android-architecture-componentsを触って感じたことを記載した記事です。

環境

  • buildToolsVersion 25.0.3
  • android.arch.lifecycle 1.0.0-alpha1

lifecycleとは

ActivityやFragmentのライフサイクルに合わせてデータを管理できるライブラリです。
ドキュメントを読んでgoogle code labのサンプルを実装した感じでは、以下のような感想を持ちました。

良い点
  • オブジェクトをActivityやFragmentのライフサイクルに関連づけられるのが良い。onDestory()等の処理が楽になりそう。アプリの停止や生存チェックが減りそう。
  • SNSや通知アプリなどのpub, subを利用するアプリが作りやすくなりそう。RxJavaのFlowableを使うとよりよくなりそう。
  • 縦画面と横画面の作り分けが楽になる。これが一番大きい。
  • Roomは、ibatisに似ている。経験者はすぐに使いこなせるのではないだろうか。RxJavaと連携もできる。
悪い点
  • Observerクラス増えすぎ。どのライブラリもObserverとSubscribeで溢れている。可読性がさらにひどくなる。。
  • 開発者に要求されるハードルがまた上がる。

触った印象では、難しくはないので、考え方に慣れることが大事なのかなと思いました。

実装

1.0.0-alpha1のLifecycleActivityはFragmentActivityを継承しているクラスなので、AppCompatActivityクラスを継承したActivityクラスでは利用できません。かといってLifecycleActivityをそのまま利用するのは機能不足すぎで話になりません。しかも、This class is a temporary implementation detail until Lifecycles are integrated with support library.とあるように、LifecycleActivityは一時的な実装なので利用する意味がありません。
なので、以下のように改造します。

変更前
{project_folder}/MainActivity.java

public class MainActivity extends AppCompatActivity implements HomeFragment.OnFragmentInteractionListener, {

    public static final String TAB_HOME = "TAB_HOME";
    public static final String TAB_COLLECTION = "TAB_COLLECTION";
    public static final String TAB_NOTICE = "TAB_NOTICE";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    // something...
}

変更後
{project_folder}/MainActivity.java
public class MainActivity extends AppCompatActivity implements LifecycleRegistryOwner, HomeFragment.OnFragmentInteractionListener, {
    private final LifecycleRegistry mRegistry = new LifecycleRegistry(this);

    @Override
    public LifecycleRegistry getLifecycle() {
        return mRegistry;
    }

    public static final String TAB_HOME = "TAB_HOME";
    public static final String TAB_COLLECTION = "TAB_COLLECTION";
    public static final String TAB_NOTICE = "TAB_NOTICE";

    public static final String TAB_HOME = "TAB_HOME";
    public static final String TAB_COLLECTION = "TAB_COLLECTION";
    public static final String TAB_NOTICE = "TAB_NOTICE";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    // something...
}

LifecycleRegistryOwnerをimplementsしてLifecycleRegistryのインスタンスをもたせます。これで、AppCompatActivityでも利用可能になります。
あとはViewModelProvidersを使えば、ViewModelのオブジェクトを管理できます。

Activityに付加したFragmentでViewModelを管理する場合は、以下のように実装します。

{project_folder}/HomeFragment.java
public class HomeFragment extends Fragment {
    public static final String TAG = "HomeFragment";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        homeModel = ViewModelProviders.of(getActivity()).get(HomeModel.class);
    }

    // something...
}

これにより、画面の回転などでonCreate()の再呼び出しをしてもViewModelを継承したモデルから値を取得することが可能になります。

結論

android-architecture-componentsはsupport libraryと同様、デファクトのライブラリになりそうな気がします。

この他にも、通知やDBでも活躍できそうなので、色々と試していきたいですね。

PICK UP

運営サイト


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2017年4月15日土曜日

【Android7.1】EventBusまとめ

  • 公開日:2017年04月15日

記事概要

EventBusの調査メモ。取り急ぎのまとめです。
プログラミングJava用にソースコード書いてgitにあげたり、動画撮ったり、英語にしてまとめるかは微妙です。純正ライブラリでないですし。アクセス数見て考えます。

環境

  • buildToolsVersion 25.0.2
  • EventBus 3.0.0
  • Android Studio 2.3.1

対象

pub, subの概念を理解している人。

git

ここのサイトから取得できます。

特徴(長所)

  • コンポーネント間の通信を簡素化
  • イベントの送信者と受信者を切り離す
  • アクティビティ、フラグメント、およびバックグラウンドスレッドで使える
  • 複雑でエラーを起こしやすい依存関係やライフサイクルの問題を避ける
  • コードをシンプルにする
  • 速い
  • 小さい(約50k)

特徴(欠点)

  • コードが直感的でない
  • Eventが増えるとコードのつながりがわかりにくくなる

Install

build.gradleファイルに以下の内容を記述します。

{project_folder}/build.gradle

dependencies {
  compile 'org.greenrobot:eventbus:3.0.0'
}

Android Studio Plugin

EventBusの欠点は、コードが直感的で無くなることです。
なので、Android Studio Pluginを導入して、コードリーディングの軽減を図るのは良い考えです。

ここのサイトから取得できます。
もしくはAndroid StudioのPluginでEventBus3で検索しましょう。

Hello EventBus

実際に実装してみましょう。
fragmentのButtonからActivityに通知してみます。

{project_folder}/MainActivity.java

  @Override
  public void onStart() {
      Log.d("MainActivity", "onStart");
      super.onStart();
      EventBus.getDefault().register(this);
  }

  @Override
  public void onStop() {
      Log.d("MainActivity", "onStop");
      super.onStop();
      EventBus.getDefault().unregister(this);
  }

  @Subscribe(threadMode = ThreadMode.MAIN)
  public void onMessageEvent(MainFragment.MessageEvent event) {
      Log.d("MainActivity", "onMessageEvent");
      Toast.makeText(getApplicationContext(), event.msg, Toast.LENGTH_SHORT).show();
  }

コードはSubscribeメソッドから記述します。メソッドには@Subscribeアノテーションを付加します。この時、@Subscribeメソッドの名前はなんでもOKです。

EventBus.getDefault().register(this);でSubscribeを登録します。registerを呼び出したクラスに@Subscribeアノテーションを追加したメソッドがないとエラーが発生します。

Error

super classes have no public methods with the @Subscribe annotation
Caused by: org.greenrobot.eventbus.EventBusException: Subscriber class com.example.xxxx.MainActivity and its super classes have no public methods with the @Subscribe annotation

また、複数回registerを呼び出すとクラッシュします。

Error

Caused by: org.greenrobot.eventbus.EventBusException: Subscriber class com.example.xxxx.MainActivity already registered to event class

以下の実装箇所で引っかかります。

Error

if (subscriptions.contains(newSubscription)) {
    throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
}

DialogやカスタムViewを使った場合も実装方法は同じです。

Configuration

不要だと思います。デフォルト設定で良いでしょう。

Sticky Events

複雑になるだけです。いりません。

Subscriber Index

EventBus version3から導入された新機能です。初期Subscribeの登録を高速化して最適化します。最高のパフォーマンスを得るために、使用が推奨されています。
まあ、使えってことです。

build.gradleファイルに以下の内容を記述します。

{project_folder}/build.gradle

android {
  defaultConfig {
    javaCompileOptions {
      annotationProcessorOptions {
        arguments = [ eventBusIndex : 'com.example.xxx.EventBusIndex' ]
      }
    }
  }
}

dependencies {
  compile 'org.greenrobot:eventbus:3.0.0'
  annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}

初期化してSubscribeを登録してindex化するので、Applicationクラスを使います。無い場合は作成します。

{project_folder}/MyApplication.java

public class MyApplication extends Application {
  @Override
  public void onCreate() {
      super.onCreate();
      EventBus.TAG = "MyApplication-EVENT";
      EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();
  }
}

新規作成の場合は、AndroidManifest.xmlも忘れないで設定します。

{project_folder}/AndroidManifest.xml

application
  android:name="com.example.xxx.MyApplication"

以上です。pub, subの処理は変わりません。なぜなら、EventBus.getDefault()メソッドでは、EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();で作成したEventBusのインスタンスを使い回すからです。
細かい動きが気になる人はコードを読んで見ると良いでしょう。

結論

EventBusは便利なライブラリです。とはいえ、コードが読みにくくなるので、階層の離れたviewからAcitivtyに伝えるなどのケース以外ではあんまり使いたくないですね。
やっぱりcallbackをなるべく使うべきな気がします。でも、RxJavaのPub, Subよりは使いやすいです。

以上です。

PICK UP

運営サイト


参照

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2017年3月4日土曜日

【Android7.1】android.support:designのsetDrawerListenerがdeprecatedになった対応方法

  • 公開日:2017年03月05日

記事概要

Androidのアプリ開発で、setDrawerListenerがdeprecatedになりました。
この記事は、その修正方法を記載した記事です。

環境

  • buildToolsVersion 25.0.2
  • com.android.support:design 25.1.1

事象

Androidアプリのコードで記載したsetDrawerListenerがdeprecatedになりました。つーかこのメソッド、Android Studioで自動生成されるんですけど……

修正方法

setDrawerListenerメソッドをaddDrawerListenerメソッドに差し替えます。

変更前
{project_folder}/MainActivity.java

        drawer.setDrawerListener(toggle);

変更後
{project_folder}/MainActivity.java

        drawer.addDrawerListener(toggle);

上記の変更でdeprecatedが消えます。
ソースコードを比較して読んでみると、確かにsetDrawerListenerのメソッドは古臭いので、変更しておきましょう。

結論

簡単な修正なので、プログラミングJavaでなく、ブログで公開しました。プログラミングJavaのサイトも引き続きよろしくお願いしましす。高度な記事もそろそろ追加していきます。

にしても、時々おかしなコード混ざってますよね。オープンソースだから、仕方ないんですけど。でも、railsよりマシかな。。。rails5.1のアップデート大変そうですね。そろそろ取り組んでいかないとダメですね。

PS : Androidを支える技術〈I〉を読んでいます。終わったら感想書くかも。。。

以上です。

PICK UP

運営サイト


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2017年2月22日水曜日

【書評】RxJavaリアクティブプログラミング

  • 公開日:2017年02月22日
  • 公開日:2017年11月26日

概要

リアクティブプログラミングを日本語で説明した初めての本です。
まだRxjavaの需要は少ないと思いますが、よくぞ出版してくれたと思います。著者と出版社に感謝します。

私はRxjavaを使い始めて1年くらいで、まだ十分に使いこなせていません。
ドキュメントとコードを読みながら四苦八苦してRxjavaを使用していますが、理解が深まればと思って本書を購入しました。

Rxjavaとは

データの通知と取得に特化したプログラミング技法です。スマートフォンアプリの開発において、強力な武器になります。
しかし、リアクティブプログラミングに慣れるには、時間がかかるでしょう。

JavaとScalaの経験があり、オブジェクトプログラミングと関数プログラミングに慣れている技術者でも多くのトライアンドエラーが必要になるでしょう。
サーバーサイドでも利用できますが、必要ないと思います。WEBで使うならフロント側のjavaScriptで導入するべきです。

本書の対象者

丁寧に説明されていますが、リアクティブプログラミングの経験がないと、理解できない可能性が高いと思います。逆に、リアクティブプログラミングの経験がある人には良書です。Rxjavaを使う開発時には、側に置いておきたい本です。索引がとっても使いやすいです。

紙面の都合上仕方のないことですが、Androidのコーディングに関する情報はほとんどありません。あくまでRxjavaの説明です。

気になったこと

指摘する内容は本の問題点というより、リアクティブプログラミングの問題です。
リアクティブプログラミングは素晴らしい技術です。しかし、学習コストが高いのが気になります。

巨人の肩に乗るという格言がありますが、この巨人の肩に乗るにはかなりのプログラミングの経験値が必要になります。

リアクティブプログラミングを理解するにはデザインパターンのObserverパターン、ビルダーパターン、イテレーターパターン等の基本は押さえてるのが前提となります。 また、それなりのスレッドの知識も必要です。Producer-Consumerパターンなどの基本は知っている必要があります。でないと、リアクティブプログラミングの何が優れているか、どこで使うべきかを理解できないでしょう。

上記の知識や技術は、Javaを利用したことのないエンジニアにはわかりづらいと思います。

一方で、リアクティブプログラミングを比較的理解しやすいのは、Java、Scala、JavaScriptに長く関わってきたエンジニアでしょう。理想はこの3つの言語でWEBとアプリ開発の両方を経験したエンジニアです。であれば、理解は早いと思います。
もしくは既存のプログラミング知識のないエンジニアなら、先入観がないので逆に理解が早いかもしれないですね。。。(理解できればですが)

まとめ

リアクティブプログラミングの経験がある人が、知識と技術を深めるのに役立つ本です。Rxjava未経験の人は、購入前に手にとって中身を確認しましょう。さっぱり理解できない場合は、まだ手に取るのは早いです。ただし、良書であるのも事実なので、今後Rxjavaを必ず使うことが決まっているなら、絶版対策として購入した方が良いかもしれません。

追記

リアクティブプログラミングの理解と習得に役立つ本を紹介します。

増補改訂版Java言語で学ぶデザインパターン入門

デザインパターンを学習するならこの本です。リアクティブプログラミングをきちんと理解するならIterator、Observer、Bulderは抑えときましょう。

Java言語で学ぶデザインパターン入門 マルチスレッド編

超良書。結城さんは説明が上手でわかりやすいです。全部目を通しましょう。分厚いけど、10日もあれば読めます。

Java並行処理プログラミング ―その「基盤」と「最新API」を究める―

これは神。スレッドの本で1番良い本です。なかなか手に入らないので、見つけたら速攻買いましょう。

関連記事

よく利用する実装方法まとめ

随分と扱えるようになってきたので、深く理解するために再度復習中です。せっかくなので、コードを残します。コードはjavaでなくkotlinで記載しています。

1. 流れを理解(確認)するサンプル。

{project_folder}/inaction/hello_world.kt

    private fun onClickRx() {
        val flowableOnSubscribe = object : FlowableOnSubscribe<String> {
            override fun subscribe(emitter: FlowableEmitter<String>) {
                val datas  = mutableListOf<String>("Hello world", "こんにちわ地球のみなさん")

                for (data in datas) {
                    if (emitter.isCancelled) {
                        Log.d("Reactive2Activity", "emitter.isCancelled");
                        return
                    }

                    Log.d("Reactive2Activity", data);
                    emitter.onNext(data)
                }

                emitter.onComplete()

            }

        }

        val subscriber = object : Subscriber<String> {

            var tempSubscription : Subscription? = null

            override fun onComplete() {
                Log.d("Reactive2 : onComplete ", Thread.currentThread().name);
            }

            override fun onNext(t: String?) {
                Log.d("Reactive2 onNext : ", t + " : " + Thread.currentThread().name);
                result.text = t

                tempSubscription?.request(1L)
            }

            // 最初
            // 購読
            override fun onSubscribe(subscription: Subscription?) {
                Log.d("Reactive2 onSubscribe ", Thread.currentThread().name)
                tempSubscription = subscription
                subscription?.request(1L)
            }

            override fun onError(t: Throwable?) {
                t?.printStackTrace()
            }

        }

        // つぎはsbcribe
        // データはバッファ
        val flowable = Flowable.create(flowableOnSubscribe, BackpressureStrategy.BUFFER)
        //flowable.subscribe(subscriber)
        // emitter
        flowable.observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber)

    }

順番は、1. Subscriber#onSubscribe 2. FlowableEmitter#onNext(), 3. FlowableEmitter#onNext() 4. FlowableEmitter#onComplete, 5. Subscriber#onNext() 6.Subscriber#onNext() 7. Subscriber#onComplete()

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年10月14日金曜日

【cocos2-dx Android】学習中につまづいた箇所 その2

  • 公開日:2016年10月15日

記事概要

cocos2d-xの学習中に発生したエラーと解決方法のまとめです。
忘備録的なメモですが、なにかの役に立てばと思いUPします。

使用している本(以下、教材)は

です。

環境

  • Android Studio 2.2.0
  • OS X El Capitan
  • android sdk 24
  • cocos2d-x 3.13.1

画面のサイズの調整

教材 p85 の画面のサイズの調整がうまくいかない。
コードは以下の通りです。

TitleScene.cpp
  // 画面サイズ
  Size visibleSize { Director::getInstance()->getVisibleSize()};
  // 背景
  Sprite* bgSprite { Sprite::create("title_bg.png")};
  // 座標の設定
  bgSprite->setPosition(visibleSize / 2);
  this->addChild(bgSprite);

画像をスケールするように、コードを以下のように変更する

TitleScene.cpp
  // 画面サイズ
  Size visibleSize { Director::getInstance()->getVisibleSize()};
  // 背景
  Sprite* bgSprite { Sprite::create("title_bg.png")};
  // 画像サイズの取得
  CCSize imgSize = bgSprite->getContentSize();
  // スケール
  bgSprite->setScale(visibleSize.width/imgSize.width, visibleSize.height/imgSize.height);
  bgSprite->setPosition(visibleSize / 2);
  this->addChild(bgSprite);

上記の実装で、画面がスケールされて表示される。
しかし、コンパイル時に以下のwarningが発生する。

terminal

warning: 'cocos2d::CCSize' is deprecated

CCSizeの実装を変更する

TitleScene.cpp
  // 画面サイズ
  Size visibleSize { Director::getInstance()->getVisibleSize()};
  // 背景
  Sprite* bgSprite { Sprite::create("title_bg.png")};
  // 画像サイズの取得
  Size imgSize = bgSprite->getContentSize();
  // スケール
  bgSprite->setScale(visibleSize.width/imgSize.width, visibleSize.height/imgSize.height);
  bgSprite->setPosition(visibleSize / 2);
  this->addChild(bgSprite);

CCSize から Size にするとwarningが消えます。
ui::Buttonなども同じように画像をスケールすることで対応できました。

画面のサイズの調整2

P104 のゲーム画面の作成で、画面サイズが自分の利用している端末だとうまくいかなくて、思いどおりに作成できない事案が発生。 調べたところ、AppDelegate.cppに以下のコードを発見。

AppDelegate.cpp
static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);

  if (frameSize.height > mediumResolutionSize.height)
  {
  director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
  }
  // if the frame's height is larger than the height of small size.
  else if (frameSize.height > smallResolutionSize.height)
  {
  director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
  }
  // if the frame's height is smaller than the height of medium size.
  else
  {
  director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
  }

自動生成のデフォルトコードでは、setContentScaleFactorでスケールサイズを決めている。
これは、端末のディスプレイサイズによらずサイズを指定するために使用する関数なので、学習初期には不要と判断して消して対応した。 マルチサイズは、フレームワークのメソッドの仕様をある程度把握してから取りかかる方が学習効率が良い。

以下のように変更した。

AppDelegate.cpp
static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);

// if (frameSize.height > mediumResolutionSize.height)
// {
// director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
// }
  // if the frame's height is larger than the height of small size.
// else if (frameSize.height > smallResolutionSize.height)
// {
// director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
// }
  // if the frame's height is smaller than the height of medium size.
// else
// {
// director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
// }
  }

コメントアウトします。

これを外すと、スケールを考える必要がなくなる。
あとは、setPositionのVec2で微調節します。

以上です

注意

学習中なので、非効率な点があるかもしれませんが、ご容赦ください。 後で見直すので、気がついたら随時修正します。

学習時は、C++未経験ならロベールのC++も一緒に利用しましょう。 本のコード説明部分のreturn部分がよく省略されているのが気になります。

学習本

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年3月18日金曜日

【コラム】Android案件を見積もる場合に考えておくことリストを読んで思ったこと

  • 公開日:2016年03月18日

記事概要

コラム記事。


アプリの見積もりは難しい

このサイトの意見に、ほぼ同意なので読んでみることをおススメします。
少しだけ追記事項をコラム風に記載しました。

外注するな

もし、あなたの会社がアプリの開発を外注で作成しようとしているなら、それは間違いなくリスクの高い仕事になる。
web開発とアプリ開発は違う。WEBと同じ感覚だと、まともなアプリは作れない。結局はWEBviewメインのアプリになるだろう。
もし、あなたが仕事を受注して開発する立場なら、かかった工数だけ請求できるように契約しておこう。基本は内製するべきということを認識しないといけない。

更新を続けろ

作成したアプリを2年も放置すれば、作成者か上級開発者以外は触れることができないアプリになるだろう。googleやappleのプラットフォームを利用するなら、彼らの開発の流れに乗らないといけない。彼らは国家からの命令をも拒否するくらい規約に忠実だ。君の意見など通らない。

純正のライブラリを使用しろ

アプリのライブラリはなるべく純正を利用しよう。Androidの進化はとてつもなく早い。素早くに対応していくためには、基本に忠実に作るのがベストプラックティスである。遠回りに見えるが、実は近道だ。

学習を続けろ

止まると死ぬ。

まとめ

つまり、アプリの受託開発はオススメしないってのが結論です。
周り全部が不幸になる可能性が高いです。内製しましょう。

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年3月6日日曜日

【Android】Error:Execution failed for task ':app:dexDebug'. Google Play Servicesの更新で起きたこと

  • 公開日:2016年03月06日

記事概要

androidのアプリ開発で発生したError:Execution failed for task ':app:dexDebug'エラーの修正方法を記載した記事です。
(この記事はJavaプログラミングでもさらに詳しく掲載予定です。)

環境

  • android sdk 23
  • Build Tools, Revision 23.0.2
  • com.google.android.gms:play-services:8.4.0

事象

Androidアプリで利用しているGoogle Play Servicesのバージョンを8.3.0から8.4.0に更新しました。その後、gradleでビルドした時にError:Execution failed for task ':app:dexDebug'が発生した。

変更前
{project_folder}/build.gradle

dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.android.support:support-v4:23.1.0'
    compile 'com.google.android.gms:play-services:8.3.0'
    compile 'com.google.code.gson:gson:2.3'
    compile files('libs/twitter4j-core-4.0.2.jar')
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile project(':libraries:facebook')
    compile 'com.android.support:cardview-v7:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.0.0'
    compile 'com.android.support:design:23.0.0'
}

変更後
{project_folder}/build.gradle

dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.android.support:support-v4:23.1.0'
    compile 'com.google.android.gms:play-services:8.4.0'
    compile 'com.google.code.gson:gson:2.3'
    compile files('libs/twitter4j-core-4.0.2.jar')
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile project(':libraries:facebook')
    compile 'com.android.support:cardview-v7:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.0.0'
    compile 'com.android.support:design:23.0.0'
}

発生箇所

android studioを使ったgradleビルド時。

エラー原因

Androidアプリでメソッド数が64k(65536)を超えるとビルド時やインストール時にエラーになる。このメソッド数はライブラリも含めてカウントされる。
つまり、Google Play Servicesのバージョンを8.3.0から8.4.0にあげたことにより、Androidアプリ全体のメソッド数が64k(65536)を超えてしまったために発生した。

修正方法

修正方法は以下のように複数あります。

  • メソッドを減らす。
  • proguardを使用する
  • multidex supportを利用する

ここではmultidex supportで解決する方法を選択します。

変更後
{project_folder}/build.gradle

    defaultConfig {
        // something

        // Enabling multidex support.
        multiDexEnabled true

    }

上記の変更でgradleビルドが可能になります。
また、Google Play Servicesは利用するライブラリだけをビルドすることもできます。修正する時間があればその方が良い選択です。現在のGoogle Play Servicesは全てのライブラリを導入すると容量が増えるので、必要なライブラリだけに絞る方が良いです。

結論

dexについて理解が浅い場合は、簡易的な修正をするだけでなく、この機会に学んでおくことをオススメします。

以上です。

PICK UP

運営サイト


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2015年10月16日金曜日

Android開発 Floating action buttonを使ってみた

  • 公開日:2015年10月16日

記事概要


androidの開発でFloating action buttonを実装しました。
この記事では、Floating action buttonの実装方法と使い方を記載しています。

環境


  • OS X Yosemite
  • Android Studio 1.4.0
  • android sdk 23(Android 6.0 Marshmallow(マシュマロ))

Floating action buttonとは


Material desginで取り入れられたボタンです。
画面の端に表示して、よく使うアクションの操作に使用されます。

他のアプリの参考になるFloating action buttonの使い方


色々なアプリを確認してみましたが、google mapの利用方法が一番良いと思いました。

実装


gradle

com.android.support:designライブラリを利用できるように設定します。


dependencies {
    compile 'com.android.support:design:23.0.0'
}

layout.xml

画面のlayoutを記載します


        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="@dimen/fab_margin"
            android:src="@android:drawable/ic_dialog_email" />

dimen.xml

マージンのサイズを指定します。直接layoutのxmlに書かないでdimen.xmlを使いましょう。


<resources>
    <dimen name="fab_margin">16dp</dimen>
</resources>

javaの実装

通常のボタンと同じ実装方法です。


    private FloatingActionButton mFab;

    mFab = (FloatingActionButton) findViewById(R.id.fab);
    this.mFab.setOnClickListener(this);

    @Override
    public void onClick(View v) {
        // something
    }

ビルドして画面を確認します。

表示されました。

まとめ


FloatingActionButtonは見栄えも使い勝手も良いボタンです。
しかし、使いどころに悩むボタンでもあります。
Google純正のアプリだと、FloatingActionButtonがうまく使われているので参考になると思います。

以上

Androidアプリ開発にオススメの本


開発にあると便利なオススメ製品


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2015年10月10日土曜日

Android開発 SDK tools version ((23)) is too old to check APIs

  • 公開日:2015年10月10日

記事概要


Android Studioを1.3から1.4にバージョンアップした時に、「SDK tools version is too old to check APIs」のエラーが発生しました。
その対応方法の記事です。

環境


  • Android Studio 1.4.0
  • OS X Yosemite

SDK tools version is too old to check APIsの発生


2015/09/30日にAndroid Studio 1.4.0が正式にリリースされました。
ということで早速アップデートしたところ以下の様なエラーが発生しました。

SDK tools version ((23)) is too old to check APIs ...

SDK toolsのエラーが古いことによるエラーの発生です。
package以下に赤い下線が表示されていますが、アプリのビルドに問題はありません。
とはいえ、放置しておくのは気持ちが悪いので以下の手順で修正しました。

  • SDK Managerを開く
  • DK Toolsタブを選択
  • Android SDK Platform-Tools 23.0.1をチェックしてアップデート
  • OKボタンを押下

インストールが終了すると、先ほど出ていたエラーが消えます。

まとめ


androidアプリの定期的なアップデートの他に、開発環境のアップデートもきっちり行っていきましょう。
最初はしんどく感じると思いますが、慣れです。
こういった直接開発に繋がらないことは遠回りに思うこともあるかと思いますが、結局は定期的なアップデートを続けることが良いアプリを作ることにも繋がります。

以上

Androidアプリ開発にオススメの本


開発にあると便利なオススメ製品


参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加
Related Posts Plugin for WordPress, Blogger...