表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
4/19

アンドロイド スマホのアプリの画面の表示の設定の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)またはアンドロイド ビュー(AndroidView)とも呼ぶようです。

 ただし、「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を除く、既存のビューは、そのままでは、指のジェスチャーのピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動しない?ようなので、拡大、縮小、移動させたい場合は、既存のビューを継承して自作する必要が有ります。

 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"

>

  <◯◯◯.ZoomableWebView

    android:id="@+id/webView"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

  />

</LinearLayout>

――――――――――――――――――――



 WebViewは、自作しなくても、次のような設定をすると、ピンチ アウトとピンチ インで拡大縮小できます。

 ただし、WebViewを自作すると、自分好みに(なめ)らかに拡大、縮小できます。

――――――――――――――――――――

webView.settings.builtInZoomControls = true

webView.settings.useWideViewPort = true

webView.settings.displayZoomControls = true

webView.settings.loadWithOverviewMode = true

webView.settings.setSupportZoom(true)

――――――――――――――――――――



 ピンチ アウト、ピンチ イン、スクロールで拡大、縮小、移動する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) …格子こうし状に画面の部品であるビューを配置できます。テーブル レイアウト(TableLayout)とは違い、複数の列をまたぐ事などができるそうです。


 コンストレイント レイアウト(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のプロジェクトに付けた名前です。

評価をするにはログインしてください。
この作品をシェア
Twitter LINEで送る
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

この作品はリンクフリーです。ご自由にリンク(紹介)してください。
この作品はスマートフォン対応です。スマートフォンかパソコンかを自動で判別し、適切なページを表示します。

↑ページトップへ