TextViewに枠線を付ける&背景色を変更する

前に作ったアプリの機能追加をしたときのメモ。

TextViewに枠線を付ける

表みたいなものを作ろうと思いTextViewを並べてみたのだが、TextViewには枠線を表示するプロパティが無く、そのままだと真っ白なハコが並んでいるだけになってしまった。
「TextView 枠線」ググってみると、次のサイトを発見。
【Android開発】スタイルにborderがないけど枠線を表示したい
XMLで四角を書いたリソースを定義しておいて、それをTextViewのBackGroundResourceプロパティに定義する。
Drawableリソースの詳細は下記にて。
Drawable resources  |  Android Developers
今回は枠線をグレー、中の色を白にしたかったのでこんな風に定義した。


    
    
    
    

試してみたところ、きちんと枠線が表示された。

TextViewの背景色を変更する

今度は白だった背景色を変更してみる。上で作ったXMLのsolidを変更してみた。例えば背景色を緑にするなら、


と定義する。最初ここを


と書いていたのだけれど、それだと背景色が変わらなかった。下のやつだと透過度=0と判断されてしまったのだろうか?(透過度=0が透明、透過度=255が不透明)
参考:
Color  |  Android Developers

TextViewの背景色を動的に変更する

続けてTextViewの背景色を動的に変更する方法について。これはsetBackGroundResource()の引数に上で定義したリソースID(ファイル名。例えばdrawable/border.xmlを参照するならR.drawable.border)を指定する。
例としては、

TextView text = (TextView)findViewById(R.id.text_1);
if (r == 0){
    text.setBackgroundResource(R.drawable.border_1);
}else{
    text.setBackgroundResource(R.drawable.border_2);
}

個人的にはXMLの中で定義したの「"#FF00FF00"」だけを差し替えたかったんだけれど、やり方が分からなかった。同じような疑問を感じてる方もいらっしゃるようで。
Drawable ResourcesのShapeをJavaで動的に作る方法がわからない - くろめも@dev
なんかうまい書き方ないのかなー。

おまけ

Twitterでも書いたけど、Androidエミュレータで画面の縦横方向を変更する方法。
いろいろな解説サイトを見るとCtrl+F11で切り替える、と書いてあった。自分の環境で試したところ、左Ctrl+F11だと切り替えられたが右Ctrl+F11だと切り替えられなかった。そういうもんなんだろうか。

Windows7のXPモードで時刻同期を無効にする

Windows7のXPモードで開発をしていて、テストなんかでOSの日付を変えようとした時のこと。
タスクバーの時計をダブルクリックして「日付と時刻のプロパティ」を開き、カレンダーで日付を変更してOK。
・・・と思ったが、もう一度「日付と時刻のプロパティ」を開くと日付が元に戻っている。
最初ドメインに参加させているせいかと思いドメインから外した状態で再度実行したがやはり同じ結果に。
どうもホストPCの日付、時刻と同期しているようだ。

というわけで、"VirtualPC"、"Windows7"、"XPモード"、"時刻同期"あたりのキーワードで検索してみると次のページがヒット。
仮想マシンの時刻同期機能を無効にする(Virtual PC編) − @IT

これを参考にvmcファイルの設定を書き変えてみた。
ちなみに自分の環境では、XPモードのvmcファイルは以下のディレクトリにあった。

C:\Users\(ユーザー名)\AppData\Local\Microsoft\Windows Virtual PC\仮想マシン\Windows XP Mode.vmc

vmcファイルをテキストエディタで開き、"host_time_sync"を検索すると、次のような記述があった。

			
				true
				15
				10
			

これを

			
				false
				15
				10
			

に変更して保存。その後VirtualPCのXPモードを起動すると日付を変更することができた。

ListViewのスクロール時に色が変わってしまうのを防ぐ

リストビューをスクロールさせた時に全選択みたいな感じでリストが真っ黒になってしまう現象が発生した。
解決方法としては、

mListView.setScrollingCacheEnabled(false);

これでOK。
ちなみに参考にしたサイトでは

ListView mListView = (ListView)findViewById(R.id.list);
mListView.setScrollingCacheEnabled(false);

こんな感じになっているけど、自分のところはListActivityを使っているので

ListView mListView = getListView();
mListView.setScrollingCacheEnabled(false);

こうなる。

参考:
ListViewをスクロールすると設定したのと別の背景色に変わってしまう問題 - 心魅 - cocoromi -
Google グループ

横向き画面でウィジェットの表示を変更する

以前作ったAndroidアプリに対するコメントで、「IS01で見るとウィジェットの文字が切れています」というものがありました。
実機が無いのでとりあえずエミュレータで画面を横向きに設定して確認してみると、なるほど文字が切れている。
僕が作ったウィジェットのレイアウトはTextViewを4段表示しているのですが、画面を横にした場合、4段目が表示されていませんでした。
というわけでプログラムの修正。

AppWidgetProvider.onUpdate()でウィジェットの描画をしているので、そこで画面の向きを取得します。

int ori = context.getResources().getConfiguration().orientation;

値はと言うと

Configuration.ORIENTATION_LANDSCAPE:横長
Configuration.ORIENTATION_PORTRAIT:縦長
Configuration.ORIENTATION_SQUARE:正方形

というのがあるみたい。

で、横向きの時は4段表示を3段表示にしよう、ということで、TextViewの一つを非表示にする処理を追加しました。

ちなみに、AppWidget上のビューを更新する場合

textview.SetVisibility(View.GONE)

ではなく、RemoteViewsを使います。

RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.appwidgetlayout);
views.setInt(R.id.appwidget_label, "setVisibility", View.GONE);

setVisibility()はViewの表示、非表示を設定するもので、以下の設定が出来ます。

View.VISIBLE:Viewを表示する。
View.INVISIBLE:Viewを非表示にする。
View.GONE:Viewを非表示にし、レイアウトを詰める。

今回はView.GONEを設定することでTextViewを1段詰めるようにしました。

こんな感じで修正したところ、とりあえずちゃんと表示されるようになりました。

参考:
widgetを非表示にして詰める方法 - hyoromoのブログ
Mtk's Blog: [Android] 画面の回転に反応するウィジットアプリケーションを作るには

SQL Server Compact EditionにはISNULL()関数が無い

Windows Mobile + .Net Compact Framework + SQL Server Compact Editionで開発したときのメモ。

SQL Server Compact EditionにはISNULL()関数が無い。

select ISNULL(col1, '') from table1;

と書くとcol1がNULLの時はTrueが、そうでないときはFalseが返される。
IS NULL構文に置き換えられているのだろうか?

ISNULL()関数が無いのでCASE式を使うことにする。

select case when col1 is null then '' else col1 end from table1;

数が多くなってきたときに面倒だなぁ。できるだけNULLを使わないようにテーブルを作ればいいのかな?

参考:
IS [NOT] NULL (SQL Server Compact Edition) | Microsoft Docs
「ISNULL() は、Microsoft SQL Server 2005 Compact Edition でサポートされている関数ではありません。」と書かれている。

SQL Server CE: Alternative to ISNULL(): CASE... END | PC Review
ISNULL()関数のかわりにCASE式を使ったサンプル

AppWidgetの背景画像を変更する

AndroidのAppWidget開発中のメモ。
AppWidgetの背景画像を変更しようとすると「ウィジェットを表示できません」と表示されてしまう。

エラー

こんな感じでAppWidgetのレイアウトを定義(途中省略)。

<LinearLayout
  android:id="@+id/appwidget_layout"
  android:background="@drawable/widgetbg">
    <TextView
      android:id="@+id/appwidget_text"
      android:text="sample" />
</LinearLayout>

更新処理でLinearLayoutのbackgroundを更新する。
AppWidget上のウィジェットを更新するにはRemoteViewsを使う。

RemoteViews views = new RemoteViews(context, R.layout.widgetlayout);
views.setInt(R.id.appwidget_layout, "setBackgroundResource", R.drawable.widgetbg_red);

こいつを実行してみたところ、AppWidgetの画面には「ウィジェットを表示できません」と表示されてしまう。

調べてみた

とりあえず、"AppWidget"、"RemoteViews"、"setBackgroundResource"といったキーワードで調べてみると、海外のメーリングリストがヒット。
Google グループ
Google グループ
どうも自分のケースと同じく、RemoteViewsを使ってsetBackgroundResourceを実行してもbackgroundが更新されないらしい。
結局解決策が見つからなかったので別の方法でチャレンジ。

FrameLayoutを使う

FrameLayoutを使い、背面にImageView、前面にLinearLayoutを配置する。

<FrameLayout>
  <ImageView
    android:id="@+id/appwidget_image" 
    android:src="@drawable/widgetbg" />
  <LinearLayout
    android:id="@+id/appwidget_layout"
    android:background="@drawable/widgetbg">
      <TextView
        android:id="@+id/appwidget_text"
        android:text="sample" />
  </LinearLayout>
</FrameLayout>

更新処理ではImageViewのsrcを更新する。

RemoteViews views = new RemoteViews(context, R.layout.widgetlayout);
views.setInt(R.id.appwidget_image, "setImageResource", R.drawable.widgetbg_red);

これだと問題なくAppWidgetの背景画像を更新できた。

Android勉強中

今月から社内勉強会でAndroidを勉強中。
いろいろ本を買い揃え、ネットから技術情報を探し、とりあえず基本的な動きは理解できるようになった。
Androidに関するページを片っ端からブクマしてったら、何がなんだか分からないリンク集が出来上がってしまったため、後で日記上に整理しようと思う。

で、今は試しにアプリケーションを作っているところなんだけど、5年ぶりくらいにJava触ったので少しずつ思い出しながらちまちまと開発を進めている。
それにしてもEclipseは便利だなぁ。

参考にさせていただいているサイト(随時追加)
Android Developers
青い鳥捕獲部 | 社怪人の余暇
スマホアプリ/Web開発ならテックファーム株式会社 |
連載インデックス「Androidで動くJavaアプリ開発入門」 - @IT