アンドロイド スマホのアプリの画面の表示の設定のXMLと、R.javaについて
アンドロイド スマホのアプリでは画面の表示の設定のXMLをLinux Mintの場合は/home/◯◯◯/AndroidStudioProjects/◇◇◇/app/src/main/res/layout/ディレクトリに置かせます。
――――――――――――――――――――
/home/◯◯◯/AndroidStudioProjects/◇◇◇/app/src/main/res/layout/
――――――――――――――――――――
◯◯◯はLinux Mintのユーザー名です。
◇◇◇はユーザーが付けたAndroid Studioのプロジェクト名です。
アンドロイド スマホのアプリでは、文字を表示するラベルやボタンなどの画面の部品をウィジェット(Widget)と呼びます。また、ウィジェット(Widget)をビュー(View)とも呼ぶようです。
ただし、「Android ウィジェット」などで検索すると別の物まで引っかかってしまうので、「Android アプリ開発 ビュー」などで検索したほうが良いです。
【既存の主なビュー(View)】
・テキスト ビュー(TextView) ……文字を表示するラベル
・オート コンプリート テキスト ビュー(AutoCompleteTextView)
・マルチ オート コンプリート テキスト ビュー(AutoCompleteTextView)
・イメージ ビュー(ImageView) ……画像の表示
・ビデオ ビュー(VideoView) ……動画の表示
・エディット テキスト(EditText) ……文字を入力できるテキスト ボックス
・ボタン(Button)
・イメージ ボタン(ImageButton)
・チェック ボックス(CheckBox)
・ラジオ ボタン(RadioButton)
・ラジオ グループ(RadioGroup)
・スピナー(Spinner) ……アダプターを設定すると、リスト ボックスにできる
・スクロール ビュー(ScrollView) ……ビューか下記のレイアウトを1つだけ縦スクロール可能にできる。2つ以上のビューを縦スクロール可能化する場合は2つ以上のビューを1つのレイアウトにまとめる。
・ホライゾンタル スクロール ビュー(HorizontalScrollView) ……横スクロール版のスクロール ビュー
・ウェブ ビュー(WebView) ……アプリ内ブラウザー。JavaScriptからアプリのActivityの処理を呼び出したりできる。ウェブ サイトとアプリの2つを提供する場合はウェブ ビューが有効の可能性が高いそうです。
・シーク バー(SeekBar)
・トグル ボタン(ToggleButton)
・レイティング バー(RatingBar)
・プログレス バー(ProgressBar)
・デート ピッカー(DatePicker)
・タイム ピッカー(TimePicker)
・デジタル クロック(DigitalClock)
・アナログ クロック(AnalogClock)
・クロノ メーター(Chronometer)
・リスト ビュー(ListView) …… 一覧表示。各行の一行分の一件分の画面の表示の設定は別のXMLファイルに書くようです。その別のXMLファイルの内容を設定するArrayAdapterのサブクラスを作成する事に成ります。アダプターと呼ばれる物のうち、ArrayAdapterを利用するのが一般的だそうです。
・チェックド テキスト ビュー(CheckedTextView)
スクロール ビューの例
――――――――――――――――――――
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<EditText
android:id="@+id/editText"
android:inputType="textMultiLine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0"
>
<requestFocus/>
</EditText>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
――――――――――――――――――――
既存のビューは、そのままでは、指のジェスチャーのピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動しないので、拡大、縮小、移動させたい場合は、既存のビューを継承して自作する必要が有ります。
ただし、ピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動するWebViewは簡単に自作できますが、ImageViewは難しいです。
さて、Android Studioで、Kotlinで既存のビューを継承した物を自作すると、何もしなくても、画面の表示の設定のXMLで利用できます。
例えば、既存のWebViewを継承してピンチ アウトとピンチ インで拡大縮小するZoomableWebView.ktを自作した場合、画面の表示の設定のXMLで「<WebView」という部分を「<◯◯◯.ZoomableWebView」に変更するだけです。
◯◯◯はKotlinのパッケージ名です。
ちなみに、WebViewには拡大縮小のzoomIn()、zoomOut()という物が用意されています。
ピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動するWebViewの自作例
――――――――――――――――――――
package ◯◯◯
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.webkit.WebView
class ZoomableWebView(
context: Context,
attributeSet: AttributeSet?,
defaultStyleAttribute: Int,
defaultStyleResourceId: Int
) : WebView(context, attributeSet, defaultStyleAttribute, defaultStyleResourceId), ScaleGestureDetector.OnScaleGestureListener {
private val scaleGestureDetector = ScaleGestureDetector(context, this)
private var lastScaleFactor = 1.0f
constructor(context: Context, attributeSet: AttributeSet?, defaultStyleAttribute: Int) : this(context, attributeSet, defaultStyleAttribute, 0)
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0, 0)
constructor(context: Context) : this(context, null, 0, 0)
override fun onTouchEvent(motionEvent: MotionEvent?): Boolean {
scaleGestureDetector.onTouchEvent(motionEvent!!)
return super.onTouchEvent(motionEvent)
}
override fun onScaleBegin(scaleGestureDetector: ScaleGestureDetector): Boolean {
return true
}
override fun onScale(scaleGestureDetector: ScaleGestureDetector): Boolean {
if ((lastScaleFactor / 0.05f).toInt() == (scaleGestureDetector.scaleFactor / 0.05f).toInt()) {
return true
}
lastScaleFactor = scaleGestureDetector.scaleFactor
//ピンチアウトの場合
//
//拡大の場合
//
if (1.0f < scaleGestureDetector.scaleFactor) {
zoomIn()
//ピンチインの場合
//
//縮小の場合
//
} else {
zoomOut()
}
return true
}
override fun onScaleEnd(scaleGestureDetector: ScaleGestureDetector) {
}
}
――――――――――――――――――――
――――――――――――――――――――
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<eliphas1810.bitflippedimageviewer.ZoomableWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
――――――――――――――――――――
ピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動するImageViewの自作例を書き残して置きますが、その自作のImageViewが複数の場合、複数のうち1つを拡大、縮小、移動すると他の物にも影響が及んでしまいました。
ピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動するImageViewの自作例
――――――――――――――――――――
package ◯◯◯
import android.content.Context
import android.graphics.Matrix
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import androidx.appcompat.widget.AppCompatImageView
class ZoomableImageView(context: Context, attributeSet: AttributeSet?, defaultStyleAttribute: Int) : AppCompatImageView(context, attributeSet, defaultStyleAttribute), ScaleGestureDetector.OnScaleGestureListener {
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)
constructor(context: Context) : this(context, null, 0)
val scaleGestureDetector = ScaleGestureDetector(context, this)
val simpleOnGestureListener = object : GestureDetector.SimpleOnGestureListener() {
override fun onScroll(motionEvent1: MotionEvent, motionEvent2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
val imageViewWidth = width
val imageViewHeight = height
val imageMatrixValues = FloatArray(9)
imageMatrix.getValues(imageMatrixValues)
val imageWidth = imageViewWidth * imageMatrixValues[Matrix.MSCALE_X]
val imageHeight = imageViewHeight * imageMatrixValues[Matrix.MSCALE_Y]
var x = 0.0f
var y = 0.0f
//縮小中の画像が画像ビューよりも小さい場合
//
//画像が画像ビューよりも小さい場合
//
if (imageWidth < imageViewWidth) {
//画像を動かさない
//x = 0.0f
//拡大中の画像が画像ビューよりも大きい場合
//
//画像が画像ビューよりも大きい場合
//画像の左端が画像ビューと画面よりも右に離れていて、更に指を左へ動かして、画像を逆方向の更に右へ動かそうとした場合
} else if (distanceX < 0.0f && 0.0f < imageMatrixValues[Matrix.MTRANS_X]) {
//画像を元にゼロに戻す
x = 0.0f - imageMatrixValues[Matrix.MTRANS_X]
//画像の右端が画像ビューと画面よりも左に離れていて、更に指を右へ動かして、画像を逆方向の更に左へ動かそうとした場合
} else if ((imageWidth + imageMatrixValues[Matrix.MTRANS_X]) < imageViewWidth && 0.0f < distanceX) {
//画像の右端を画像ビューと画面の右端に戻す
//
//画像の右端と、画像ビューと画面の右端の差分だけ戻す
//
x = imageViewWidth - (imageWidth + imageMatrixValues[Matrix.MTRANS_X])
//その他の場合
} else {
//指で動かした分だけ逆方向へ動かす
x = 0.0f - distanceX
}
//縮小中の画像が画像ビューよりも小さい場合
//
//画像が画像ビューよりも小さい場合
//
if (imageHeight < imageViewHeight) {
//画像を動かさない
//y = 0.0f
//拡大中の画像が画像ビューよりも大きい場合
//
//画像が画像ビューよりも大きい場合
//画像の上端が画像ビューと画面よりも下に離れていて、更に指を上へ動かして、画像を逆方向の更に下へ動かそうとした場合
} else if (distanceY < 0.0f && 0.0f < imageMatrixValues[Matrix.MTRANS_Y]) {
//画像を元にゼロに戻す
y = 0.0f - imageMatrixValues[Matrix.MTRANS_Y]
//画像の下端が画像ビューと画面よりも上に離れていて、更に指を下へ動かして、画像を逆方向の更に上へ動かそうとした場合
} else if ((imageHeight + imageMatrixValues[Matrix.MTRANS_Y]) < imageViewHeight && 0.0f < distanceY) {
//画像の下端を画像ビューと画面の下端に戻す
//
//画像の下端と、画像ビューと画面の下端の差分だけ戻す
//
y = imageViewHeight - (imageHeight + imageMatrixValues[Matrix.MTRANS_Y])
//その他の場合
} else {
//指で動かした分だけ逆方向へ動かす
y = 0.0f - distanceY
}
//画像を移動
imageMatrix.postTranslate(x, y)
//画像ビューの枠内の画像を再描画
invalidate()
return super.onScroll(motionEvent1, motionEvent2, distanceX, distanceY)
}
}
val gestureDetector = GestureDetector(context, simpleOnGestureListener)
val minScaleFactor = 0.5f
override fun onTouchEvent(motionEvent: MotionEvent?): Boolean {
gestureDetector.onTouchEvent(motionEvent!!)
scaleGestureDetector.onTouchEvent(motionEvent!!)
return true
}
override fun onScaleBegin(scaleGestureDetector: ScaleGestureDetector): Boolean {
return true
}
override fun onScale(scaleGestureDetector: ScaleGestureDetector): Boolean {
var scaleFactor = scaleGestureDetector.scaleFactor
if (scaleFactor == 1.0f) {
return true
}
if (scaleFactor < minScaleFactor) {
scaleFactor = minScaleFactor
}
super.setScaleType(ScaleType.MATRIX)
val imageMatrix = super.getImageMatrix()
imageMatrix.postScale(scaleFactor, scaleFactor)
super.setImageMatrix(imageMatrix)
val layoutParams = super.getLayoutParams()
layoutParams.width = (super.getWidth() * scaleFactor).toInt()
layoutParams.height = (super.getHeight() * scaleFactor).toInt()
super.setLayoutParams(layoutParams)
return true
}
override fun onScaleEnd(scaleGestureDetector: ScaleGestureDetector) {
}
}
――――――――――――――――――――
アンドロイド スマホのアプリでは、文字を表示するラベルやボタンなどの画面の部品であるビュー(View)の並べ方をレイアウト(Layout)と呼びます。XMLではビューのタグをレイアウトのタグで囲む事に成ります。
【既存の主なレイアウト(Layout)】
・リニア レイアウト(LinearLayout) …画面の部品であるビューを縦に並べるか、横に並べます。
・フレーム レイアウト(FrameLayout) …XMLの上から順に、先の物の上に後の物を重ね合わせて表示していきます。
・リラティブ レイアウト(RelativeLayout) …画面の部品であるビューを画面の端、画面の中央、別のビューの上下左右などに相対的な位置指定で並べます。
・コンストレイント レイアウト(ConstraintLayout) …リラティブ レイアウト(RelativeLayout)に似ています。リラティブ レイアウトよりも柔軟に画面の部品であるビューを配置できるそうです。
・テーブル レイアウト(TableLayout) …ウェブページのHTMLのtableタグのように
・グリッド レイアウト(GridLayout) …
コンストレイント レイアウト(ConstraintLayout)では、画面やビューの上の辺をトップ(Top)、左の辺をスタート(Start)、右の辺をエンド(End)、下の辺をボトム(Bottom)と呼びます。
最も下のビュー以外のビューは、そのトップが画面のトップか他のビューのボトムに対応している事と、そのスタートが画面のスタートか他のビューのエンドに対応している事と、そのエンドが画面のエンドか他のビューのスタートに対応している事を書きます。
そして、ビューは対応関係の中間に配置されるので、左のビューを左上に寄せる場合は、水平のバイアスと、垂直のバイアスを0.0に設定します。右下に寄せる場合は1.0に設定します。中間は0.5です。
コンストレイント レイアウト(ConstraintLayout)の例
――――――――――――――――――――
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/fileName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
<Button
android:id="@+id/readButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/read"
app:layout_constraintTop_toBottomOf="@id/fileName"
app:layout_constraintStart_toStartOf="parent"
/>
<Button
android:id="@+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save"
app:layout_constraintTop_toBottomOf="@id/fileName"
app:layout_constraintStart_toEndOf="@id/readButton"
app:layout_constraintEnd_toEndOf="parent"
/>
<EditText
android:id="@+id/text"
android:inputType="textMultiLine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/readButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0"
>
<requestFocus/>
</EditText>
</androidx.constraintlayout.widget.ConstraintLayout>
――――――――――――――――――――
ウェブページのHTMLのCSSのようにマージンやパディングといった余白や、文字の色や背景の色や、右寄せなども指定できます。
アンドロイド スマホのアプリの画面の表示の設定のXMLのタグのandroid:layout_width属性やandroid:layout_height属性の属性値のmatch_parentは画面の最大や、格納してくれている親要素の画面の部品の中での最大を意味します。
――――――――――――――――――――
android:layout_width="match_parent"
android:layout_height="match_parent"
――――――――――――――――――――
アンドロイド スマホのアプリの画面の表示の設定のXMLのタグのandroid:layout_width属性やandroid:layout_height属性の属性値のwrap_contentは内容に合わせた大きさを意味します。例えば、文字を表示するラベルであるテキスト ビュー(TextView)では文字を全て十分に表示できる大きさを意味します。
――――――――――――――――――――
android:layout_width="wrap_content"
android:layout_height="wrap_content"
――――――――――――――――――――
ちなみに、「dp」という単位を付けて数値で指定する方法も有るようです。
ちなみに、文字の大きさ、フォント サイズを指定する場合は「sp」という単位を利用するようです。
アンドロイド スマホのアプリの画面の表示の設定のXMLで、文字を表示するラベルやボタンなどの画面の部品であるビュー(View)に、唯一に特定するための名前であるidを付ける事ができます。Android Studioは自動でXMLファイルを解析してR.javaファイルを作成してくれるので、Kotlinなどのプログラムの中でR.idのidの名前のメンバーとしてidを参照する事ができます。それにより、名前の指定を誤ってしまった時にコンパイル エラーと成るので、気づく事ができます。
Android StudioにJavaやKotlinなどのプログラムのコードをコピペして、「import android.R」が自動で追加されてしまったら、削除してください。
「android.R」は、「R.layout.activity_main」や「R.id.◯◯◯」の「R」とは違います。
そのため、「import android.R」が有ると、コンパイル エラーが発生してしまいます。
各画面のボタンなどの各部品のidの全てが、1つの「R.id」に同列でまとめられます。
そのため、各画面の各部品のidは「画面の名前 + 部品に表示するか利用する情報の名前」というルールで付けたほうが良いかもしれない、と個人的に思っております。間違っているかもしれませんが。
例えば、「musicListArtistName」や「musicDetailArtistName」です。
――――――――――――――――――――
android:id="@+id/◯◯◯"
――――――――――――――――――――
R.id.◯◯◯
――――――――――――――――――――
※R.id.◯◯◯の内容はint型の数値です。
文字を表示するラベルの部品であるテキスト ビュー(TextView)のidが「musicListArtistName」の場合の例
――――――――――――――――――――
android:id="@+id/musicListArtistName"
――――――――――――――――――――
findViewById<TextView>(R.id.musicListArtistName)?.text = "西川の兄貴"
――――――――――――――――――――
ちなみに、"@+id/◯◯◯"ではなく"@id/◯◯◯"はコンストレイント レイアウト(ConstraintLayout)などで他の、画面の部品であるウィジェット(Widget)を指定する時に利用します。
――――――――――――――――――――
app:layout_constraintTop_toBottomOf="@id/◯◯◯"
――――――――――――――――――――
例
――――――――――――――――――――
app:layout_constraintTop_toBottomOf="@id/musicListArtistName"
――――――――――――――――――――
Android Studioは自動でXMLファイルを解析してR.javaファイルを作成してくれるので、「R.layout.拡張子無しのXMLファイル名」という形で、アンドロイド スマホのアプリの画面の表示の設定のXMLファイルを参照できます。アクティビティ(Activity)のonCreate()内のsetContentView()のパラメーターに指定したりします。
――――――――――――――――――――
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
try {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//ここに処理を書きます。
} catch (exception: Exception) {
Toast.makeText(applicationContext, exception.toString(), Toast.LENGTH_LONG).show()
throw exception
}
}
}
――――――――――――――――――――
「R.layout.activity_main」は「/home/◯◯◯/AndroidStudioProjects/◇◇◇/app/src/main/res/layout/activity_main.xml」ファイルの参照です。
◯◯◯はLinux Mintのユーザー名です。
◇◇◇はユーザーがAndroid Studioのプロジェクトに付けた名前です。
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます