20210425のAndroidに関する記事は4件です。

【Android】Build failed: NDK is not installed エラーの解消方法(MacOS)

※ Mac です。 ビルドした際に、 Build failed: NDK is not installed とエラーが出る場合がある。 NDKのインストール NDKとCMakeをインストールする。 Preferences -> SDK Toolsタブを開き、以下のチェックボックスにチェックを入れる。 NDK (Side by Side) CMake OKを押してインストールする。 NDKのパスとバージョン確認 デフォルトなら、/Library/Android/sdk内にあるかと思う。 /Users/ユーザー名/Library/Android/sdk/ndk/23.0.7196353 local.propatiesに追記 ビルドしたいプロジェクト内の、local.propatiesにNDKへのパスを追記する。 local.propaties ## This file must *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. #Wed Apr 14 09:47:31 JST 2021 sdk.dir=/Users/ユーザー名/Library/Android/sdk + ndk.dir=/Users/ユーザー名/Library/Android/sdk/ndk/23.0.7196353 ビルドする うまくいけば、ビルドできる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】srcとbackgroundの違い

ImageViewやImageButtonで画像リソースを設定するときに用いる 基本的にはbackgroundでリソースを指定していたが、他人の実装ソースではsrcを使用していたので把握している限りの違いを確認する。 Stack Overflowで同じ質問がヒットしたのだがそこから抜粋すると background指定 リソースのオリジナルサイズ関係なしに指定したwidthとheightに調整される <ImageButton android:id="@+id/button" android:layout_width="60dp" android:layout_height="60dp" android:background="@drawable/resource_button"/> ※実際の細かい調整は省略 src指定 リソースのオリジナルサイズで表示される <ImageButton android:id="@+id/button" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/resource_button" android:background="#00000000"/> ※実際の細かい調整は省略 この場合だと、縦横は60dpで指定しているもののリソースサイズはそれより大きいため途中で切られてしまう。もしbackgroundの時のようにサイズ調整したい場合はandroid:scaleType="fitCenter"を指定するとOK Stack Overflowに戻るが The src to an ImageView has additional features: different scaling types adjustViewBounds for setting bounds to match image dimensions some transformations such as alpha-setting とあるように、srcの方が様々な設定ができる様子。 またbackgroundは動的に変えることができ、Javaだと private ImageView view; /* * 中略 */ view.setBackgroundResource(R.drawable.resource_button); //画像リソースを指定する場合 Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.btn, null); view.setBackground(drawable); //drawableファイルを設定する場合 view.setBackground(null); //リソースをクリアする場合 と変えられるが、レイアウトファイルでsrc指定すると上の処理を実行しても反映されない。background指定内容の前面にsrc指定内容が表示されている様子。 以下はbackgroundを黒色指定して、srcにリソースを指定した場合。 <ImageView android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/ic_launcher_foreground" android:background="@color/black"/> 結論 オリジナルリソースの縦横の比率を維持したいならsrc指定がベスト 動的に変えたいならbackground指定(src指定したリソースを動的に変える方法があるのか不明) 試した環境 Android Studio4.1.2 Android10
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android/Java】srcとbackgroundの違い

ImageViewやImageButtonで画像リソースを設定するときに用いる 基本的にはbackgroundでリソースを指定していたが、他人の実装ソースではsrcを使用していたので把握している限りの違いを確認する。 Stack Overflowで同じ質問がヒットしたのだがそこから抜粋すると background指定 リソースのオリジナルサイズ関係なしに指定したwidthとheightに調整される <ImageButton android:id="@+id/button" android:layout_width="60dp" android:layout_height="60dp" android:background="@drawable/resource_button"/> ※実際の細かい調整は省略 src指定 リソースのオリジナルサイズで表示される <ImageButton android:id="@+id/button" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/resource_button" android:background="#00000000"/> ※実際の細かい調整は省略 この場合だと、縦横は60dpで指定しているもののリソースサイズはそれより大きいため途中で切られてしまう。もしbackgroundの時のようにサイズ調整したい場合はandroid:scaleType="fitCenter"を指定するとOK Stack Overflowに戻るが The src to an ImageView has additional features: different scaling types adjustViewBounds for setting bounds to match image dimensions some transformations such as alpha-setting とあるように、srcの方が様々な設定ができる様子。 またbackgroundは動的に変えることができ、Javaだと private ImageView view; /* * 中略 */ view.setBackgroundResource(R.drawable.resource_button); //画像リソースを指定する場合 Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.btn, null); view.setBackground(drawable); //drawableファイルを設定する場合 view.setBackground(null); //リソースをクリアする場合 と変えられるが、レイアウトファイルでsrc指定すると上の処理を実行しても反映されない。background指定内容の前面にsrc指定内容が表示されている様子。 以下はbackgroundを黒色指定して、srcにリソースを指定した場合。 <ImageView android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/ic_launcher_foreground" android:background="@color/black"/> 結論 オリジナルリソースの縦横の比率を維持したいならsrc指定がベスト 動的に変えたいならbackground指定(src指定したリソースを動的に変える方法があるのか不明) 試した環境 Android Studio4.1.2 Android10
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】RadioButtonを複数行に配置する

複数行のRadioButtonが標準で用意されてなかったので、作ってみたところ、意外と詰まったのでまとめてみました。 イメージは下の通りです。少しレイアウトが弄ってありますが、詳しい説明は省かせていただきます。 忙しい方は3. RadioGroupをカスタマイズするをご覧ください。 1. TableLayoutをカスタマイズする おすすめ度 ★★★★☆ TableLayoutをRadioGroup代わりに利用する方法です。調べると大体がこの方法に行き着くと思います。 参考 RadioGridGroup.java import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.IdRes; import android.util.AttributeSet; import android.view.View; import android.widget.RadioButton; import android.widget.TableLayout; import android.widget.TableRow; public class RadioGridGroup extends TableLayout implements View.OnClickListener { private static final String TAG = "ToggleButtonGroupTableLayout"; private int checkedButtonID = -1; /** * @param context */ public RadioGridGroup(Context context) { super(context); // TODO Auto-generated constructor stub } /** * @param context * @param attrs */ public RadioGridGroup(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override public void onClick(View v) { if (v instanceof RadioButton) { int id = v.getId(); check(id); } } private void setCheckedStateForView(int viewId, boolean checked) { View checkedView = findViewById(viewId); if (checkedView != null && checkedView instanceof RadioButton) { ((RadioButton) checkedView).setChecked(checked); } } /* (non-Javadoc) * @see android.widget.TableLayout#addView(android.view.View, int, android.view.ViewGroup.LayoutParams) */ @Override public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) { super.addView(child, index, params); setChildrenOnClickListener((TableRow) child); } /* (non-Javadoc) * @see android.widget.TableLayout#addView(android.view.View, android.view.ViewGroup.LayoutParams) */ @Override public void addView(View child, android.view.ViewGroup.LayoutParams params) { super.addView(child, params); setChildrenOnClickListener((TableRow) child); } private void setChildrenOnClickListener(TableRow tr) { final int c = tr.getChildCount(); for (int i = 0; i < c; i++) { final View v = tr.getChildAt(i); if (v instanceof RadioButton) { v.setOnClickListener(this); } } } /** * @return the checked button Id */ public int getCheckedRadioButtonId() { return checkedButtonID; } /** * Check the id * * @param id */ public void check(@IdRes int id) { // don't even bother if (id != -1 && (id == checkedButtonID)) { return; } if (checkedButtonID != -1) { setCheckedStateForView(checkedButtonID, false); } if (id != -1) { setCheckedStateForView(id, true); } setCheckedId(id); } /** * set the checked button Id * * @param id */ private void setCheckedId(int id) { this.checkedButtonID = id; } public void clearCheck() { check(-1); } @Override protected void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); this.checkedButtonID = ss.buttonId; setCheckedStateForView(checkedButtonID, true); } @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.buttonId = checkedButtonID; return savedState; } static class SavedState extends BaseSavedState { int buttonId; /** * Constructor used when reading from a parcel. Reads the state of the superclass. * * @param source */ public SavedState(Parcel source) { super(source); buttonId = source.readInt(); } /** * Constructor called by derived classes when creating their SavedState objects * * @param superState The state of the superclass of this view */ public SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeInt(buttonId); } public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } } 3×2のレイアウトです。 <com.test.customviews.RadioGridGroupの部分は自分の環境に合ったものに変更しておいて下さい。 activity_main.xml <com.test.customviews.RadioGridGroup android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TableRow> <RadioButton android:id="@+id/rad1" android:checked="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text1" /> <RadioButton android:id="@+id/rad2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text2" /> </TableRow> <TableRow> <RadioButton android:id="@+id/rad3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text3" /> <RadioButton android:id="@+id/rad4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text4" /> </TableRow> <TableRow> <RadioButton android:id="@+id/rad5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text5" /> <RadioButton android:id="@+id/rad6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text6" /> </TableRow> </com.test.customviews.RadioGridGroup> XMLでandroid:checked="true"を指定すると、RadioButtonのチェックが外れなくなりバグるためコード上で指定する必要があります。 MainActivity.kt val group = findViewById<GridRadioGroup>(R.id.radioSubject) group.check(R.id.group) メリット TableLayoutなので比較的自由にレイアウトをカスタマイズすることができる デメリット RadioButtonのチェック状態が変更された時に呼ばれるリスナーsetOnCheckedChangeListenerが無い → 独自リスナーを実装することで解決 RadioGridGroup.java public class RadioGridGroup extends TableLayout implements View.OnClickListener { private static final String TAG = "ToggleButtonGroupTableLayout"; private int checkedButtonID = -1; private OnCheckedChangeListener mOnCheckedChangeListener; // ・・・ 略 private void setCheckedId(int id) { if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, id); } this.checkedButtonID = id; } // ・・・ 略 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } public interface OnCheckedChangeListener { void onCheckedChanged(GridRadioGroup gridRadioGroup, int checkedId); } } MainActivity.kt group.setOnCheckedChangeListener { _, checkedId -> Log.d("GridRadioGroup", "${checkedId}が選択されました") } RadioButtonにsetOnClickListenerを呼んだときにバグる → 当てはまる人はごく少数だと思われますが、私の場合このバグが致命的だったため別の方法を探すことにしました 基本的なデメリットはRadioGroupが継承されてないことのみだと思います。 2. RadioGroupを3つ並べる おすすめ度 ★★☆☆☆ RadioGroupを3つ並べてコードで操作する方法です。クラスの拡張等が必要ありません。 参考 activity_main.xml <RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content"> <RadioGroup android:id="@+id/group1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/rad1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text1" /> <RadioButton android:id="@+id/rad2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text2" /> </RadioGroup> <RadioGroup android:id="@+id/group2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/rad3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text3" /> <RadioButton android:id="@+id/rad4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text4" /> </RadioGroup> <RadioGroup android:id="@+id/group3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/rad5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text5" /> <RadioButton android:id="@+id/rad6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text6" /> </RadioGroup> </RadioGroup> コード側です。仕組みは簡単で、一行目のRadioGroupが選択されたら二行目・三行目のチェックを解除。二行目のRadioGroupが選択されたら一行目・三行目のチェックを解除、といった仕組みです。 MainActivity.kt val group1 = root.findViewById<RadioGroup>(R.id.group1) val group2 = root.findViewById<RadioGroup>(R.id.group2) val group3 = root.findViewById<RadioGroup>(R.id.group3) listener = RadioGroup.OnCheckedChangeListener { group, checkedId -> if (checkedId != -1) when (group.id) { R.id.group1 -> { group2.clearCheck() group3.clearCheck() } R.id.group2 -> { group1.clearCheck() group3.clearCheck() } R.id.group3 -> { group1.clearCheck() group2.clearCheck() } } } group1.setOnCheckedChangeListener(listener) group2.setOnCheckedChangeListener(listener) group3.setOnCheckedChangeListener(listener) 一見動きそうに見えますが、実はこの状態では動きません。clearCheck()が呼ばれた時にもOnCheckedChangeListenerが呼ばれるからです。 そのため、対処方法としてはclearCheck()を呼ぶ度にリスナーの登録を解除する必要があります。 MainActivity.kt class MainActivity : AppCompatActivity() { private lateinit var listener: RadioGroup.OnCheckedChangeListener override fun onCreate(savedInstanceState: Bundle?) { // ・・・ 略 val group1 = findViewById<RadioGroup>(R.id.group1) val group2 = findViewById<RadioGroup>(R.id.group2) val group3 = findViewById<RadioGroup>(R.id.group3) listener = RadioGroup.OnCheckedChangeListener { group, checkedId -> if (checkedId != -1) when (group.id) { R.id.group1 -> { checkAnswer(group2) checkAnswer(group3) } R.id.group2 -> { checkAnswer(group1) checkAnswer(group3) } R.id.group3 -> { checkAnswer(group1) checkAnswer(group2) } } } group1.setOnCheckedChangeListener(listener) group2.setOnCheckedChangeListener(listener) group3.setOnCheckedChangeListener(listener) // ・・・ 略 } private fun checkAnswer(radioGroup: RadioGroup) { radioGroup.setOnCheckedChangeListener(null) radioGroup.clearCheck() radioGroup.setOnCheckedChangeListener(listener) } } メリット RadioGroupのメソッドが使える デメリット コードが多い & 見た目が良くない listenerをグローバル変数に置く必要がある RadioGroupが使えるため独自実装等が必要ありませんが、保守性があまり良くないです。 3. RadioGroupをカスタマイズする おすすめ度 ★★★★★ 見つけるのに結構時間がかかりました。仕組みは 2. と同じです。 RadioGroup代わりに利用できるようカスタマイズされていたので有り難く使わせていただきます。 MultiRowsRadioGroup.java import android.content.Context; import android.os.Build.VERSION; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.RadioGroup; import java.util.ArrayList; /** * 可以多行布局的RadioGroup,但是会用掉子RadioButton的OnCheckedChangeListener * A RadioGroup allow multiple rows layout, will use the RadioButton's OnCheckedChangeListener */ public class MultiRowsRadioGroup extends RadioGroup { public MultiRowsRadioGroup(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MultiRowsRadioGroup(Context context) { super(context); init(); } private void init() { setOnHierarchyChangeListener(new OnHierarchyChangeListener() { public void onChildViewRemoved(View parent, View child) { if (parent == MultiRowsRadioGroup.this && child instanceof ViewGroup) { for (RadioButton radioButton : getRadioButtonFromGroup((ViewGroup) child)) { radioButton.setOnCheckedChangeListener(null); } } } @Override public void onChildViewAdded(View parent, View child) { if (parent == MultiRowsRadioGroup.this && child instanceof ViewGroup) { for (final RadioButton radioButton : getRadioButtonFromGroup((ViewGroup) child)) { int id = radioButton.getId(); // generates an id if it's missing if (id == View.NO_ID) { if (VERSION.SDK_INT >= 17) id = View.generateViewId(); else id = radioButton.hashCode(); radioButton.setId(id); } if (radioButton.isChecked()) { check(id); } radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { radioButton.setOnCheckedChangeListener(null); check(buttonView.getId()); radioButton.setOnCheckedChangeListener(this); } } }); } } } }); } private boolean checking = false; @Override public void check(int id) { if (checking) return; checking = true; super.check(id); checking = false; } private ArrayList<RadioButton> getRadioButtonFromGroup(ViewGroup group) { if (group == null) return new ArrayList<>(); ArrayList<RadioButton> list = new ArrayList<>(); getRadioButtonFromGroup(group, list); return list; } private void getRadioButtonFromGroup(ViewGroup group, ArrayList<RadioButton> list) { for (int i = 0, count = group.getChildCount(); i < count; i++) { View child = group.getChildAt(i); if (child instanceof RadioButton) { list.add((RadioButton) child); } else if (child instanceof ViewGroup) { getRadioButtonFromGroup((ViewGroup) child, list); } } } } <com.test.customviews.RadioGridGroupの部分は自分の環境に合ったものに変更しておいて下さい。 activity_main.xml <com.test.customviews.MultiRowsRadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/rad1" android:checked="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text1" /> <RadioButton android:id="@+id/rad2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text2" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/rad3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text3" /> <RadioButton android:id="@+id/rad4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text4" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/rad5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text5" /> <RadioButton android:id="@+id/rad6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text6" /> </LinearLayout> </com.test.customviews.MultiRowsRadioGroup> メリット RadioGroupのメソッドが使える XMLだけで完結している デメリット 多分無し さいごに 自由にレイアウトをカスタマイズしたい方以外は 3. をおすすめします
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む