20200621のAndroidに関する記事は7件です。

AndroidのWebView#shouldInterceptRequestでリクエストをinterceptするときに忘れがちなこと

AndroidのWebViewでHTTPレスポンスのハンドリングやタイムアウトを独自に実装したいときに、shouldInterceptRequestをオーバーライドして、独自にHTTP通信を実装することがありますよね。

サンプルなので大雑把な実装ですが、例えば以下のような感じに実装したとしましょう。

override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
    val latch = CountDownLatch(1)
    var res: InputStream? = null

    val call = createOkHttpClient().newCall(Request.Builder().url(request?.url.toString()).method("POST", RequestBody.create(null, "hoge")).build())
    call.enqueue(object: Callback {
        override fun onFailure(call: Call, e: IOException) {
            latch.countDown()
        }

        override fun onResponse(call: Call, response: Response) {
            res = response.body()?.byteStream()
            latch.countDown()
        }
    })

    latch.await()
    return WebResourceResponse("text/html", "UTF-8",res)
}

private val cookieStore = HashMap<String, MutableList<Cookie>>()

fun createOkHttpClient(): OkHttpClient {
    return OkHttpClient.Builder()
        .cookieJar(object: CookieJar {
            override fun saveFromResponse(url: HttpUrl, cookies: MutableList<Cookie>) {
                cookieStore[url.host()] = cookies
        }

            override fun loadForRequest(url: HttpUrl): MutableList<Cookie> {
                val cookies = cookieStore[url.host()]
                return cookies ?: ArrayList()
            }
        })
        .build()
}

でも、これを使うときは要注意。
例えば、以下のようなHTMLを取得する場合を考えてみましょう。

<html>                                                                                                                                                                                                                                        
<body>
<script type="text/javascript">
  function doPost() {
    document.TestForm.submit();
  }
</script>

<h1>Test</h1>

<form id="TestForm" name="TestForm" action="http://192.168.100.2:3000/hoge" method="post">
  <input type="hidden" name="hoge" value="hogeVal"/>
  <input type="hidden" name="fuga" value="fugaVal"/>
  <input type="submit" value="submit">
</form>
<script type="text/javascript">
  doPost();
</script>
</body>
</html>

WebViewはHTML解析機能を持っていますから、上記のHTML読み込み時に、doPost関数が呼び出され、

タグに定義されたhttp://192.168.100.2:3000/hogeに対して、自動的にリクエストを送信します。

このとき、shouldInterceptRequestでリソースの読み込みをWebViewに任せていれば(shouldInterceptRequestをオーバーライドしていなければ)、
<input>タグのhidden属性の値を自動的にPOSTしてくれますが、開発者が独自にOkHTTPなどでリクエストを実装する際は、HTMLの内容を解析して自前で付与しないといけません。(デフォルトではhidden属性の値は付与されない)

以下のようなサーバを立てて、ログを見てみましょう。

{-# LANGUAGE OverloadedStrings #-}                                                                                                                                                                                                            
module Main where

import Web.Scotty
import Control.Monad.IO.Class (liftIO)

main :: IO ()
main = scotty 3000 $ do
  post "/test.html" $ file "./static/test.html" >> setHeader "Content-Type" "text/html"
  post "/hoge" $ do
    (liftIO . putStrLn $ ("Access to /hoge. Headers: " :: String)) >> headers >>= liftIO . print
    (liftIO . putStrLn $ ("Params: " :: String)) >> params >>= liftIO . print
    text "hoge success"
shouldInterceptRequestをオーバーライドしない場合
Access to /hoge. Headers: 
[("Host","192.168.100.151:3000"),("Connection","keep-alive"),("Content-Length","25"),("Cache-Control","max-age=0"),("Origin","http://192.168.100.151:3000"),("Upgrade-Insecure-Requests","1"),("Content-Type","application/x-www-form-urlencoded"),("User-Agent","Mozilla/5.0 (Linux; Android 9; Android SDK built for x86 Build/PSR1.180720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36"),("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"),("Referer","http://192.168.100.151:3000/test.html"),("Accept-Encoding","gzip, deflate"),("Accept-Language","ja-JP,en-US;q=0.9"),("X-Requested-With","com.badlogic.masaki.webviewjsinterfacesample")]
Params: 
[("hoge","hogeVal"),("fuga","fugaVal")]
shouldInterceptを上記実装でオーバーライドした場合
Access to /hoge. Headers: 
[("Content-Length","4"),("Host","192.168.100.151:3000"),("Connection","Keep-Alive"),("Accept-Encoding","gzip"),("User-Agent","okhttp/3.10.0")]
Params: 
[]

HTMLのhidden属性に定義されていた内容がPOSTされていませんね。これだとサーバから意図したレスポンスが返却されなくなってしまうでしょう。
その他、User-Agentなどのヘッダー情報も代わってしまいますから、shouldInterceptRequestをオーバライドするときは、この点も注意。

hidden属性の値をPOSTするためには、HTMLの解析が必要になってきます。
ここら辺は既に情報が色々出回っています。

HTMLの内容の取得方法は以下とか参考になりました。
https://stackoverflow.com/questions/8200945/how-to-get-html-content-from-a-webview

OkHttpで、application/x-www-form-urlencodedのPOSTパラメータを設定する方法は以下とかが
参考になりました。
https://stackoverflow.com/questions/35756264/how-do-i-post-data-using-okhttp-library-with-content-type-x-www-form-urlencoded

以前の記事でも同じようなこと言いましたが、WebViewの目的はHTMLのレンダリングだから、WebAPI呼び出しに使うようなものではないですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Modern Android] Jetpack Compose その2

Composeのサンプルコードを見ながら、分析しようと思います。
JetNewというComposeのサンプルを見つけました。

はじめる

image.png

https://github.com/android/compose-samples/tree/master/JetNews

Readmeを読む

Jetnews is a sample news reading app, built with Jetpack Compose. The goal of the sample is to showcase the current UI capabilities of Compose.
To try out this sample app, you need to use the Canary version of Android Studio 4.0, and import the project from the Android Samples following the steps here.
Compose is not available in earlier versions of Android Studio and downloading this github repo directly and opening it will most likely result in build errors.

  • Use Rows and Columns to arrange the contents of the UI
  • Add an AppBar
  • Use MaterialTypography and opacity to style the text
  • Use Shape to round the corners of the images
  • Use elevation to make the Cards stand out from the background

これを読んで見るとFlutterを似ていると感じますね。

コードを見る

1

setContentにUIのComposeを使う。

package com.example.jetnews.ui

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.ui.core.setContent
import com.example.jetnews.JetnewsApplication

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val appContainer = (application as JetnewsApplication).container
        setContent {
            JetnewsApp(appContainer = appContainer)
        }
    }
}

2

  • JetnewsThemeとAppContentというCompose関数がある。
  • DataとModelは今回無視します。
@Composable
fun JetnewsApp(appContainer: AppContainer) {
    JetnewsTheme {
        AppContent(
            interestsRepository = appContainer.interestsRepository,
            postsRepository = appContainer.postsRepository
        )
    }
}

3

JetnewsThemeはTheme.ktで宣言されている。
MaterialThemeはなんだろう。

Theme.kt
@Composable
fun JetnewsTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable() () -> Unit
) {
    MaterialTheme(
        colors = if (darkTheme) DarkThemeColors else LightThemeColors,
        typography = themeTypography,
        shapes = shapes,
        content = content
    )
}

4

  • なるほど、Material design specificationの Compose関数である。
  • Color, typography , shapes, contentをパラメータで使ってる。
/**
 * A MaterialTheme defines the styling principles from the Material design specification.
 *
 * Material components such as [Button] and [Checkbox] use values provided here when retrieving
 * default values.
 *
 * It defines colors as specified in the [Material Color theme creation spec](https://material.io/design/color/the-color-system.html#color-theme-creation),
 * typography defined in the [Material Type Scale spec](https://material.io/design/typography/the-type-system.html#type-scale),
 * and shapes defined in the [Shape scheme](https://material.io/design/shape/applying-shape-to-ui.html#shape-scheme).
 *
 * All values may be set by providing this component with the [colors][ColorPalette],
 * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the overall
 * theme of elements within this MaterialTheme.
 *
 * Any values that are not set will inherit the current value from the theme, falling back to the
 * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top
 * of your application, and then separate MaterialTheme(s) for different screens / parts of your
 * UI, overriding only the parts of the theme definition that need to change.
 *
 * @sample androidx.ui.material.samples.MaterialThemeSample
 *
 * @param colors A complete definition of the Material Color theme for this hierarchy
 * @param typography A set of text styles to be used as this hierarchy's typography system
 * @param shapes A set of shapes to be used by the components in this hierarchy
 */
@Composable
fun MaterialTheme(
    colors: ColorPalette = MaterialTheme.colors,
    typography: Typography = MaterialTheme.typography,
    shapes: Shapes = MaterialTheme.shapes,
    content: @Composable () -> Unit
) {
    ProvideColorPalette(colors) {
        val indicationFactory: @Composable () -> Indication = remember { { RippleIndication() } }
        Providers(
            IndicationAmbient provides indicationFactory,
            TypographyAmbient provides typography,
            ShapesAmbient provides shapes
        ) {
            ProvideTextStyle(value = typography.body1, children = content)
        }
    }
}
  • これはFlutterのMaterialAppのthemeと一緒だと思う。

image.png

https://api.flutter.dev/flutter/material/MaterialApp-class.html

5

元に戻して、AppContentのCompose関数をみてみよう

  • Crossfade関数はFadeAnimationを使うための関数みたい
  • FlutterのFadeTransition Widgetと似ていると思う。
@Composable
private fun AppContent(
    postsRepository: PostsRepository,
    interestsRepository: InterestsRepository
) {
    Crossfade(JetnewsStatus.currentScreen) { screen ->
        Surface(color = MaterialTheme.colors.background) {
            when (screen) {
                is Screen.Home -> HomeScreen(postsRepository = postsRepository)
                is Screen.Interests -> InterestsScreen(interestsRepository = interestsRepository)
                is Screen.Article -> ArticleScreen(
                    postId = screen.postId,
                    postsRepository = postsRepository
                )
            }
        }
    }
}

終わりに

今回はここまでです。
つづく。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初めてのEpoxy

入社して3ヶ月経ちそうですが、まだEpoxyを触ったことなかったので備忘録として書いていきます。
Epoxyを使うとRecyclerViewを簡単に実装できるみたいです!(中毒性があるので注意らしい)

実装

Gradle

まずはEpoxyを使うためにGradleに依存関係を記述します。

build.gradle
    def epoxy_version = "3.11.0"
    implementation "com.airbnb.android:epoxy:$epoxy_version"
    // databinding使用するなら
    implementation "com.airbnb.android:epoxy-databinding:${epoxy_version}"
    kapt "com.airbnb.android:epoxy-processor:$epoxy_version"

package-info

gradleに依存関係を記述したら、package-info.javaファイルをプロジェクト内に作成します。

package-info.java
@EpoxyDataBindingLayouts({R.layout.recyclerview_item})
package com.example.todo;

import com.airbnb.epoxy.EpoxyDataBindingLayouts;

@EpoxyDataBindingLayoutsアノテーションでレイアウトファイルを指定するとModelが自動生成してくれます。
ここで一旦ビルドをかけてください。

layout

過去の記事のxmlファイルをDataBindingするために<layout>属性で囲います。後に書くControllerからTodoTitleを受け取って表示させます。

recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="todoTitle"
            type="String" />
    </data>

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:foreground="?android:attr/selectableItemBackground"
        app:cardElevation="10dp">

        <LinearLayout
            android:id="@+id/LinearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@android:color/white"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/sampleImg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:contentDescription="@string/recycler_picture"
                app:srcCompat="@mipmap/ic_launcher_round" />

            <TextView
                android:id="@+id/sampleTxt"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="@{ todoTitle }"
                tools:text="TODO"
                android:textSize="30sp" />

        </LinearLayout>
    </androidx.cardview.widget.CardView>
</layout>

Controller

Controllerは引数が一つの時はTypedEpoxyController<List<Todo>>()を継承します。

これは引数2つの場合は、Typed2EpoxyController()
3つ、Typed3EpoxyController()
4つ、Typed4EpoxyController()

今回は、表示するリストだけをもらえればいいので、TypedEpoxyController()を選択しました。

EpoxyController.kt
class RecyclerViewController(
    lifecycleOwner: LifecycleOwner,
    viewModel: MainViewModel
) : TypedEpoxyController<List<Todo>>() {
    init {
        viewModel.todoList.observe(lifecycleOwner, ::setData)
    }
    override fun buildModels(data: List<Todo>?) {
        data?.forEach {
            recyclerviewItem {
                id(modelCountBuiltSoFar)
                todoTitle(it.todoTitle)
            }
        }
    }
}

順を追ってControllerを見ていきましょう。buildModels()setData()が呼ばれると実行されます。そのため今回はRoomに保存しているLiveDataが更新させるたびにsetData()を呼ぶようにObserveを書きました。

buildModels()内に表示させるものを書いていきます。引数でもらったdataを自動生成された拡張関数recyclerviewItemで表示させます。

inline fun ModelCollector.recyclerviewItem(
    modelInitializer: RecyclerviewItemBindingModelBuilder.() -> Unit
) {
    add(
        RecyclerviewItemBindingModel_().apply {
            modelInitializer()
        }
    )
}

毎回add()を書かずに済むのでとても便利ですね!(これが自動生成されるなんて)
id()とは、表示される要素毎に重複しないものを設定して上げる必要があります。これを指定すると表示させる要素の差分などを判別してくれるらしい。とりあえず被らないようにmodelCountBuiltSoFarを入れました。これは、Epoxyで表示させている要素の数です。idの付け方で迷ったらこれにしてます。

Activity

あとは同じみの記述をするだけでリスト表示ができました! ViewHolderやらを書かなくて済むのはとてもいい感じです。

MainActivity.kt
        recyclerViewController = RecyclerViewController(this, mainViewModel)
        main_recycler_view.apply {
            this.adapter = recyclerViewController.adapter
            this.layoutManager = LinearLayoutManager(this@MainActivity)
        }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】MergeAdapterを使ってBanner + GridItemのパターンを実装する

概要

巷によくあるアプリのパターンとして、画面の上に横長のバナーやレイアウトを置いて、その下に格子状のレイアウトを置くというものがあります。

SmartNews

グノシー

このデザインに対応するためのよくある実装として、一つのRecylerAdapterで、ViewHolderを複数用意して、item毎にViewHolderを切り替えるといったものがあります。
しかし、ロジックが複雑化するので、実装コストや後のメンテナンスコストが増えてしまう原因でもあります。

今回はよくあるこのパターンを、recyclerviewのalpha版に実装されているMergeAdapterを使って実装していきます。

Sample

https://github.com/alpha2048/MergeAdapterTest

スクリーンショット 2020-06-21 17.00.08.png

解説

MergeAdapterはrecyclerviewの1.2.0のalpha02から入っています。

    implementation "androidx.recyclerview:recyclerview:1.2.0-alpha03"

実装はとても簡単です

  1. Banner用のAdapterを作成
  2. GridItem用のAdapterを作成
  3. MergeAdapterに上の2つをマージする

Banner用のAdapter

class BannerAdapter() : RecyclerView.Adapter<ItemBannerViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemBannerViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = ItemListBannerBinding.inflate(layoutInflater, parent, false)
        return ItemBannerViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ItemBannerViewHolder, position: Int) {
    }

    override fun getItemCount(): Int {
        return 1
    }
}

class ItemBannerViewHolder(val binding: ItemListBannerBinding) : RecyclerView.ViewHolder(binding.root)

GridItem用のAdapter

class GridItemAdapter (private val viewModel: MainViewModel) : RecyclerView.Adapter<ItemGridViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemGridViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = ItemListGridItemBinding.inflate(layoutInflater, parent, false)
        return ItemGridViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ItemGridViewHolder, position: Int) {
        holder.binding.image.load(viewModel.repoItems[position].owner.avatar_url)
    }

    override fun getItemCount(): Int {
        return viewModel.repoItems.size
    }

}

class ItemGridViewHolder(val binding: ItemListGridItemBinding) : RecyclerView.ViewHolder(binding.root)

この2つをMergeAdapterにマージする

        val bannerAdapter = BannerAdapter()
        val gridItemAdapter = GridItemAdapter(viewModel)

        val mergeAdapter = MergeAdapter(
            bannerAdapter,
            gridItemAdapter
        )

        binding.recyclerView.apply {
            val gridLayoutManager = GridLayoutManager(context,3)
            gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(position: Int): Int = if (position == 0) 3 else 1
            }
            layoutManager = gridLayoutManager
            adapter = mergeAdapter
        }

注意点として、LayoutManagerはGridLayoutManagerを使うので、バナーのように1列に表示する場合はSpanSizeの制御をきちんと入れましょう。

あとがき

簡単な実装で、性質の違うデータ、レイアウトを別々のAdapterで管理できるのはとてもよいですね!
地味にいろんなところで使えそうなので、安定版のリリースが待ち遠しいです。

参考資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Espresso入門

はじめに

AndroidでUIテストをするためには何を使うのが良いか調べて見たところ、
単一のアプリのUIテスト方法として EspressoがDeveloperGuideでも紹介されていたので、試してみました。

導入〜テスト作成まで

AndroidStudioで簡単なプログラムを作成して、それに対するUIテストを書いてみました。

が、面倒くさそう難しそうなので、書くのは大変そうですね...

いい方法がないか調べていると、DeveloperGuideにもこんなページが..

Espresso テスト レコーダーで UI テストを作成する

この方法が使えるならと..試しみました。。

SampleにAndroidStudioのプロジェクト作成で一発で作成できるLoginActivityを..

スクリーンショット 2020-06-21 12.06.50.png

出来上がるアプリはこんな感じのシンプルな画面です。

プロジェクトを作成して、Espressoを実行..

スクリーンショット 2020-06-21 11.22.14.png

アプリが起動して、IDとパスワードを入力して、ボタンをタップしてみました。
すると、以下のキャプチャのように記録されます。
(マシン性能によりそうですが、実際は結構重く、入力もすんなりできませんでした..)

スクリーンショット 2020-06-21 11.46.55.png

OKをタップするとテストクラスを出力できます。

コードはこんな風に出力されます。
テストクラスなので、実行できます。

@LargeTest
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {

    @Rule
    @JvmField
    var mActivityTestRule = ActivityTestRule(LoginActivity::class.java)

    @Test
    fun loginActivityTest() {
        val appCompatEditText = onView(
            allOf(
                withId(R.id.username),
                childAtPosition(
                    allOf(
                        withId(R.id.container),
                        childAtPosition(
                            withId(android.R.id.content),
                            0
                        )
                    ),
                    0
                ),
                isDisplayed()
            )
        )
        appCompatEditText.perform(replaceText("test"), closeSoftKeyboard())

以下省略

「Add Assertion」ボタンを押せば、キャプチャのようにアサーションを追加できます。
(ダイアログもできるのですが、レイアウト位置が正しく設定されず手直しが必要です..)

スクリーンショット 2020-06-21 11.48.03.png

まとめ

ものによっては手直しが必要ですし、ボイラーコードになりがちなのでメンテナンステストもかかりそうですが、
(UIテスト自体コストも高いし..)
UIテストはコストが高いからだけで今まで避けてきたので意外とハードルは高くないのかなと思いました。

ログインやエラーハンドリングのようなそのものはあまり変わらない部分であれば導入してみるのも良いかと思いました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AndroidでDividerを描画する方法

これは何

アンドロイドアプリを開発している際、任意の場所に区切り線を描画したいことがあるかと思います。
区切り線の描画方法について検索しても、情報が乱立していてどれが正しいのか分からなかったのですが、おそらく正解であろう方法を見つけたのでまとめました。

dividerを設定する方法

答えはこちらのデモアプリにありました。

Material Components Catalog App

以下のxml要素をdivierを描画したいところに設定するだけです。

layout.xml
<!--    horizontal divider    -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="?android:attr/listDivider" />


<!--    vertical divider     -->
    <View
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:background="?android:attr/listDivider" />

マテリアルデザインを導入している場合は、dark themeに切り替えても自動的に色を反転してくれます。

参考リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Androidでカレンダーのレイアウトを全力で自作する

概要

前回は曜日の部分だけ作ったので、今回は日付の部分を作っていきたいと思います。

全力で自作

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/sunday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sun"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/monday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mon"
            app:layout_constraintEnd_toEndOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/sunday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/tuesday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tue"
            app:layout_constraintEnd_toEndOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/monday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/wednesday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Wed"
            app:layout_constraintEnd_toEndOf="@id/thursday"
            app:layout_constraintStart_toEndOf="@+id/tuesday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/thursday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Thu"
            app:layout_constraintEnd_toEndOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/wednesday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/friday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Fri"
            app:layout_constraintEnd_toEndOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/thursday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/saturday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sat"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/friday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/cell_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="2"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="3"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="4"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/thursday"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="5"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="6"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="7"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="8"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/cell_1" />


        <TextView
            android:id="@+id/cell_12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="9"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@+id/cell_2" />

        <TextView
            android:id="@+id/cell_13"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="10"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@+id/cell_3" />

        <TextView
            android:id="@+id/cell_14"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="11"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@+id/cell_15"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@+id/cell_4" />

        <TextView
            android:id="@+id/cell_15"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="12"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@id/cell_1" />

        <TextView
            android:id="@+id/cell_16"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="13"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@+id/cell_6" />

        <TextView
            android:id="@+id/cell_17"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="14"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@id/cell_1" />


        <TextView
            android:id="@+id/cell_21"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="15"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cell_11" />


        <TextView
            android:id="@+id/cell_22"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="16"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@+id/cell_12" />

        <TextView
            android:id="@+id/cell_23"
            android:layout_width="27dp"
            android:layout_height="34dp"
            android:text="17"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@+id/cell_13" />

        <TextView
            android:id="@+id/cell_24"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="18"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@+id/cell_15"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@+id/cell_14" />

        <TextView
            android:id="@+id/cell_25"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="19"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@+id/cell_15" />

        <TextView
            android:id="@+id/cell_26"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="20"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@+id/cell_16" />

        <TextView
            android:id="@+id/cell_27"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="21"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@+id/cell_17" />

        <TextView
            android:id="@+id/cell_31"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="22"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cell_21" />


        <TextView
            android:id="@+id/cell_32"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="23"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@+id/cell_22" />

        <TextView
            android:id="@+id/cell_33"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="24"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@+id/cell_23" />

        <TextView
            android:id="@+id/cell_34"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="25"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/cell_15"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@+id/cell_24" />

        <TextView
            android:id="@+id/cell_35"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="26"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@+id/cell_25" />

        <TextView
            android:id="@+id/cell_36"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="27"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@+id/cell_26" />

        <TextView
            android:id="@+id/cell_37"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="28"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@+id/cell_27" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

とりあえず書いてみたが....
実行してみると、、、、

スクリーンショット 2020-06-21 0.04.35.png

微調節

なんかおかしい....真ん中の2つだけおかしいがそこだけ見ても違いがわからなかった...が下記のように修正したところ

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/sunday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sun"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/monday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mon"
            app:layout_constraintEnd_toEndOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/sunday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/tuesday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tue"
            app:layout_constraintEnd_toEndOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/monday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/wednesday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Wed"
            app:layout_constraintEnd_toEndOf="@id/thursday"
            app:layout_constraintStart_toEndOf="@+id/tuesday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/thursday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Thu"
            app:layout_constraintEnd_toEndOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/wednesday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/friday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Fri"
            app:layout_constraintEnd_toEndOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/thursday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/saturday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sat"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/friday"
            app:layout_constraintTop_toTopOf="@+id/sunday" />

        <TextView
            android:id="@+id/cell_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1"
            app:layout_constraintBottom_toTopOf="@id/cell_11"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="2"
            app:layout_constraintBottom_toTopOf="@id/cell_12"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="3"
            app:layout_constraintBottom_toTopOf="@id/cell_13"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="4"
            app:layout_constraintBottom_toTopOf="@id/cell_14"
            app:layout_constraintEnd_toStartOf="@id/thursday"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="5"
            app:layout_constraintBottom_toTopOf="@id/cell_15"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="6"
            app:layout_constraintBottom_toTopOf="@id/cell_16"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="7"
            app:layout_constraintBottom_toTopOf="@id/cell_17"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@id/sunday" />

        <TextView
            android:id="@+id/cell_11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="8"
            app:layout_constraintBottom_toBottomOf="@id/cell_21"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/cell_1" />


        <TextView
            android:id="@+id/cell_12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="9"
            app:layout_constraintBottom_toBottomOf="@id/cell_22"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@+id/cell_2" />

        <TextView
            android:id="@+id/cell_13"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="10"
            app:layout_constraintBottom_toBottomOf="@id/cell_23"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@+id/cell_3" />

        <TextView
            android:id="@+id/cell_14"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="11"
            app:layout_constraintBottom_toBottomOf="@id/cell_24"
            app:layout_constraintEnd_toStartOf="@+id/cell_15"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@+id/cell_4" />

        <TextView
            android:id="@+id/cell_15"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="12"
            app:layout_constraintBottom_toBottomOf="@id/cell_25"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@id/cell_5" />

        <TextView
            android:id="@+id/cell_16"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="13"
            app:layout_constraintBottom_toBottomOf="@id/cell_26"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@+id/cell_6" />

        <TextView
            android:id="@+id/cell_17"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="14"
            app:layout_constraintBottom_toBottomOf="@id/cell_27"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@id/cell_7" />


        <TextView
            android:id="@+id/cell_21"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="15"
            app:layout_constraintBottom_toBottomOf="@id/cell_31"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cell_11" />


        <TextView
            android:id="@+id/cell_22"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="16"
            app:layout_constraintBottom_toBottomOf="@id/cell_32"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@+id/cell_12" />

        <TextView
            android:id="@+id/cell_23"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="17"
            app:layout_constraintBottom_toBottomOf="@id/cell_33"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@+id/cell_13" />

        <TextView
            android:id="@+id/cell_24"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="18"
            app:layout_constraintBottom_toBottomOf="@id/cell_34"
            app:layout_constraintEnd_toStartOf="@+id/cell_15"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@+id/cell_14" />

        <TextView
            android:id="@+id/cell_25"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="19"
            app:layout_constraintBottom_toBottomOf="@id/cell_35"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@+id/cell_15" />

        <TextView
            android:id="@+id/cell_26"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="20"
            app:layout_constraintBottom_toBottomOf="@id/cell_36"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@+id/cell_16" />

        <TextView
            android:id="@+id/cell_27"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="21"
            app:layout_constraintBottom_toBottomOf="@id/cell_37"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@+id/cell_17" />

        <TextView
            android:id="@+id/cell_31"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="22"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/monday"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cell_21" />


        <TextView
            android:id="@+id/cell_32"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="23"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/tuesday"
            app:layout_constraintStart_toEndOf="@+id/cell_1"
            app:layout_constraintTop_toBottomOf="@+id/cell_22" />

        <TextView
            android:id="@+id/cell_33"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="24"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/wednesday"
            app:layout_constraintStart_toEndOf="@+id/cell_2"
            app:layout_constraintTop_toBottomOf="@+id/cell_23" />

        <TextView
            android:id="@+id/cell_34"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="25"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/cell_15"
            app:layout_constraintStart_toEndOf="@+id/cell_3"
            app:layout_constraintTop_toBottomOf="@+id/cell_24" />

        <TextView
            android:id="@+id/cell_35"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="26"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/friday"
            app:layout_constraintStart_toEndOf="@+id/cell_4"
            app:layout_constraintTop_toBottomOf="@+id/cell_25" />

        <TextView
            android:id="@+id/cell_36"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="27"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/saturday"
            app:layout_constraintStart_toEndOf="@+id/cell_5"
            app:layout_constraintTop_toBottomOf="@+id/cell_26" />

        <TextView
            android:id="@+id/cell_37"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="28"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/cell_6"
            app:layout_constraintTop_toBottomOf="@+id/cell_27" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

スクリーンショット 2020-06-21 0.10.13.png

いい感じになりました!
TopやBottomをちゃんとした上下の要素ではなく1列目のを指定した場所があったことが問題だった模様?
ConstraintLayout便利なようで便利じゃないような...わかったようなわからないような.....

次回

ほんとは枠線とかを入れてみたいが全然やり方が分からなかったので明日からはそこを少し調べていきたいと思います..!!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む