NakamuraYoichiのblog

プログラマー NakamuraYoichi のアウトプット欲を満たすためのブログ。(iwanao さんの tweetにインスパイアされてこのブログを作りました。)

Androidのタブが広がったり広がらなかったり

現象

Xamarin.Formsで作っているアプリの,あるTabbedPageのタブがAndroidの画面を回転させるとキュッと中央に寄る,という話がありました。こんな感じです。

720x1280P 2720x1280L 2

対策


同じ問題で困っている人がいるはずだと思ってググったところ,次のような記事を見つけました。

Tab not taking full width on Tablet device [Using android.support.design.widget.TabLayout] - stackoverflow

確かにTabbar.axmlにこのおまじないを入れると,タブは広がるようになりました。

でもこれは本当にTabbar.axmlに手を入れるべきなのでしょうか。Androidの方に問題があるのでは?

仕様?

マテリアル デザインのタブのところを確認してみると...

Tabs - Components - Material design guidelines

なんと中央に寄っている例があるじゃないですか。どうやら仕様の範囲内のようですね。まあ,バグなんてそうそうあるものではありません。するとTabbar.axmlもそのままでいいのかもしれません。

挙動

というわけで,ざっと調べてみました。

タブ数PortraitLandscape
1広がらない広がらない
2広がる広がらない
3広がる広がる

720x1280P 720x1280L

タイトルの文字数が多い場合も同様でした。広げれば入りきるであろう場合でも,広げられずに折り返され,省略されました。

longtitle

解像度によって変わるかも,と思って試したのですが,720x1280,1080x1920,2160x3840ではすべて同様でした。

OSによる差異はKitKat,Lollipop,Marshmallowで確認しましたが,ありません。

いまいち釈然としませんが,こういうものなのでしょう。

Telerik Kendo GridのデータとModelのデータを交換する

Telerik Kendo GridとModelのデータ交換をなるべくASP.NET MVCに任せたい,という話です。なぜModelとやり取りするのか,なぜGridから直接APIを呼ばないのか,というと,submitするまでデータベースを更新したくない,編集中の画面全体をキャンセルしたい,と思ったので。

Model→Grid

ロード時にModelからGridに渡すのは簡単で,Telerikのドキュメントにもありますが,次のようにします。

Html.Kendo().Grid(Model) @*Model自身が配列*@
Html.Kendo().Grid(Model.Hoges) @*メンバーHogesが配列*@

Grid→Model

submit時にGridからModelに渡すには,次の記事を参考にしました。Gridに限らず応用できる場面は多いと思います。

カラムのClientTemplateでname属性を例えば次のように付ければよさそうです。

.ClientTemplate("<input type='hidden' name='Hoges[0].Id' value='#= Id #' />#= Name #");

添え字を取得するjavascript functionを用意します。dataSourceのindexOfメソッドを使います。

function getIndexOf(dataItem) {
var grid = $('#grid').data('kendoGrid');
return grid.dataSource.indexOf(dataItem);
}

結果,ClientTemplateは次のようになります。

.ClientTemplate("<input type='hidden' name='Hoges[#= getIndexOf(data) #].Id' value='#= Id #' />#= Name #");

チェックボックス

チェックボックスは少し難しくて,value属性とchecked属性の両方を設定しないとGrid→Modelが行かないです,たぶん。事情はこのへんの記事で。

offのときにfalseを送れるように,ってことでしょうか。hiddenを別建てする方が正式なのかもしれません。とりあえず,if-elseを使って次のようなClientTemplateになります。

.ClientTemplate(
"# if (Flag) { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='true' checked />" +
"# } else { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='false' />" +
"# } #");

グリッド内のチェックボックスを直接編集するためには次のようなコードが必要だと,Telerikのフォーラムで紹介されています,が...

$('#grid .k-grid-content').on('change', 'input.chkbx', function (e) {
  var grid = $('#grid').data('kendoGrid'),
    dataItem = grid.dataItem($(e.target).closest('tr'));
  dataItem.set(e.target.name, this.checked);
});

が,これは'Hoges[0].'を付けない場合の書き方です。今回はデータ交換のために'Hoges[0].'を付けたので,次のようにしてみました。

$('#grid .k-grid-content').on('change', 'input.chkbx', function (e) {
  var grid = $('#grid').data('kendoGrid'),
    dataItem = grid.dataItem($(e.target).closest('tr'));
  dataItem.set(e.target.name.split('.').pop(), this.checked);
});

inputの方にclass='chkbx'を追加するのを忘れずに。

.ClientTemplate(
"# if (Flag) { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='true' checked class='chkbx' />" +
"# } else { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='false' class='chkbx' />" +
"# } #");

ソフトウェアとマラソン

ソフトウェア技術者はマラソンを走るとよい,という英語の記事があったのでざっくり紹介します。

準備
長い距離を走るには特別な準備が必要。アーキテクチャの選択も同じ,目的を持ち,調査と原則に基づいて行おう。
リスク管理
実際のレースでは不測の事態が起こるもの。アーキテクチャの弱点を見つけてリスクを識別して注意を払いながら進めよう。
休憩
レース途中で歩いたりスピードを落としたりして休むことも必要。休みの日は休むこと。ときどき別のプロジェクトでリフレッシュしよう。
情熱
スタート時は元気,30kmを過ぎたら地獄,ゴールが見えるとラストスパートがかかる。プロジェクトも同じ,マラソンで精神を鍛えておくといいんじゃないかな。

(原文) What I learned about software architecture from running a marathon by Ted Malaska

筆者のテッドさんはダイエットのために走り始めたそうですが,「走った分だけ食っていいんだぜ」とも言っています :-D

記事検索
  • ライブドアブログ