JUGEMテーマ:パソコン
新年あけましておめでとうございます。
皆さまいかがお過ごしでしょうか?
約1年ぶりのご無沙汰になりましたが、決してブログを辞めたとかそういう話ではありません。
これからもマイペースでぼちぼちやっていこと思いますので、今後ともどうぞよろしくお願いいたします。
さて、突然ですが、本当に突然にPCのモニタの電源が入らなくなりました。
↓こいつです。
電源ボタンを押しても電源が入らない、というか、「押せた」感がなくなってしまいました。
↓この右端のボタンです。
銀色に塗装されたプラスチックのボタンで、電源が入るとボタンの電源マークがLEDでグリーンに点灯する仕組みになっています。
この電源ボタンなんですが、最初からあまり押しやすいボタンではありませんでした。
最初のうちこそ、グッと押し込むと「カチッ」とスイッチが押された感触があったのですが、しばらく使っているうちにボタンがしっかり戻ってこなくなり、カチッという感触もなくなりました。
それでもボタンを「ぐりぐり」っとこねくり回すように押すとLEDが点灯して電源が入ったので、ずっとそうやって使ってきたのですが、今朝、電源を入れようとボタンを押したところ、全く反応がありません。ぐりぐりこねってみても何の反応も感触もありません。かるくタッピング、シェイキングかましてみても応答ありません。いつか来るかとは思っていましたが、ついに来てしまいました。
状況から見ておそらくこの電源ボタン周りの問題で、何かが壊れたか、接点が摩耗したか、そんなところではないかと思うのですが、外から見ただけでは良く判りません。
分解してみようと思うのですが、目に見えるネジを全部外しても、ちっともなにも外れてくれません。外し方が判りません・・・
仕方がないので、「Dell ディスプレイ 電源ボタン 押せない」とかでググってみました。
良く出てくるのが、電源ボタンが回ってしまって押せなくなっているというもの。
このタイプはボタンの向きを直してやれば電源が入るそうなのですが、残念ながら私の場合は回ってはいませんでした。
次に見つけたのがこちら。
『皆さんのモニターの主電源ボタン壊れませんか?』のクチコミ掲示板|価格.com
こちらもボタンが回ってしまう系のトラブル報告が多かったのですが、中に1つ、「せいもあ」さんの投稿に、モニタのベゼル(前面の枠の部分)を取り外した写真と、「背中を押された」という、YouTubeの動画のリンクが!
Dell 2407WFP Monitor Power Button Repair Part 1
(Part 4までありました)
ちょっと型番は違います(私のはE228WFPcでした)が、見たところ構造は似ているようですし、ボタンの形も似ているので行けそうな気がします。
ということで、じっくり一通り動画で勉強してから、分解に取り掛かりました。
まずは、スタンドを外します。
これはスタンド取り付け部の下にボタンがあるので、それを押しながらモニタ下部を前面側に持ち上げると、普通に外れます。
次に裏返して、スタンドに隠れていた部分にあるネジを4本外します。
この時点ではまだ何も起きません。次にいよいよベゼルを外しにかかります。隙間に薄めのマイナスドライバーをねじ込んでいったのですが、これが結構大変です。
ベゼルは、次の絵のような構造で嵌っています。これは画面が上を向くように平たく置いた液晶画面を縦に真っ二つにして、断面を横から見ている状態と思ってください。
こんな構造なので、下の図のように外枠を外側に引っ張ってやると、引っかかりが外れベゼルが外れます。
しかしこの「外枠を外側に」引っ張るというのがなかなか難しいんです。上の図を見て頂くと分かるように、外枠を引っ張るためにはまず、ベゼルと外枠の間にマイナスドライバーか何かをねじ込んで、これで外枠を引っかけて外側に引っ張りつつ、ベゼルは上に引っ張る、ということをしなくてはいけません。しかし、まずこの「マイナスドライバーを隙間に突っ込む」をやった段階で、ベゼルと外枠が引っかかった状態で、無理やりベゼルを上に引っ張った状態になります。なので、ここで無理をすると、ベゼルの引っかかり部分がちぎれてしまうんです。
実際はこうなります。
全体の2〜3割くらい、こんな感じにしてしまいました。こうならないようにするには、なるべく外枠が柔らかい部分、具体的には画面上部の長い部分のまん中あたりから外しにかかれば良かったかな、と若干後悔しましたが、まあ済んでしまったものは仕方ない。可動部でもないので、多少壊れたくらいならどうってことはありません。
が、お試しになる場合は、自己責任でよろしくお願いします。
上手く外れると、こうなります。
さて、外れたベゼルですが、電源ボタン部分には基盤がくっついていて、この基盤がリボン状のケーブルで本体につながっています。なので、無理に引っ張らないでください。
そーっと持ち上げたら、基盤を止めているネジを外します。
これでやっとスイッチ部分を見ることが出来ます。
基盤側はこんな感じになっています。
スイッチらしきものが5つ並んでいます。左から、入力切替ボタン、メニューボタン、メニュー操作用のマイナスボタンとプラスボタン、そして一番右のスイッチが電源ボタンです。電源ボタンのすぐ右にある、白い四角で囲われているのが、電源ボタン用のLEDです。
試しに直接手で押してみると、しっかりカチカチ接点がつながる感触がします。スイッチそのものが機械的に壊れているわけではなさそうです。にもかかわらず、電源ボタンを押したときに感触が無いということは、電源ボタンからこの接点を押すまでの機構のどこかが壊れているということです。だんだん絞れてきました。
そしてスイッチの裏側はこんな感じです。
上下反転した状態になっています。
大体基盤と対応した位置にボタンがあるようですが、1か所、電源ボタンだけ少し右に離れた位置にあります。スイッチの真上というよりもLEDの真上位の位置にボタンがあります。これは一体どういうことでしょうか?
と、頭をひねっていたら、何かコロコロっとボタンのあたりから転がり落ちてきたものがありました。
これは・・・・!!
そう、これは電源ボタンの一部、ボタンの指で押す部分の脇についていたタブで、実際にスイッチを押していた部分でした。図の赤い部分にぴったり嵌ります。
なるほど、スイッチを実際に押す部分が折れて外れてしまっていたら、いくらボタンを押してもスイッチが入らないわけです。
しかし、一体どうしてこんなところが折れてしまったんでしょう?
ボタンをちょこちょこ押してみながら動きを確かめ、構造を確認していったのですが、そうするうちに全貌が見えてきました。
まずこのボタンの構造は次のようになっています。
赤い部分が一体型の柔らかいプラスチックでできています(実際は左の4つのボタンの部分も一体です)。固定部とかいた太い部分は、ベゼルにしっかり固定されていて動きません。ボタンが押されると、曲げばねと書いた部分の固定部側の根本付近が曲がると同時に、ねじりばねと書いた部分がねじれることで、ボタンをほぼ真下に押すことが出来るような構造になっています。この2つのヒンジでストロークを出す方式は一般的な構造で、ここではそれを柔らかくて弾性のあるプラスチックを使って実現しています。
ただ、問題はその次です。ボタンを指で押したとき、「力点」、すなわち押す場所はボタンの中央ですが、構造上ボタンを支えているのが「可動支点」と書いた部分、そして実際にスイッチを押している部分が「作用点」になるわけですが、この3点の位置関係がご覧の通りL字に曲がっているんです。ボタンを押したら光るようにしたい、そのためにはボタンの真下にはLEDを置く必要がある、したがって作用点はボタンの真下からはずらす必要がある、スペースの関係上3点を1直線状に置くことが出来ないので仕方なくL字にした、ということなのだと思います。もちろんL字にしては絶対いけないということはありません。しかし、この弱いプラスチックで作った構造でこのオフセット荷重を入れると、細いねじりばねに、ねじりだけではなく曲げと引っ張りが入ってしまいます。こんなことをしたら細いねじりばねはひとたまりもありません。実際、上の図で言うと右側のねじりばねが切れてしまっていました。この後さらに左側のねじりばねも切れてしまうと、ボタン部分が完全に構造から外れてしまい、自由に回ることが出来る状態になります。そしてボタンが回ってしまうと、作用点がスイッチから外れてしまうので、回ってしまった電源ボタンをいくら押しても電源が入らない、という状況になるわけです。この状態なら回ってしまった電源ボタンを正しい位置に戻してテープか何かで固定することで、一応電源スイッチを押すことが出来るようになるわけです。これが良く報告されている電源ボタンが回ってしまう故障モードの仕組みでした。
一方、今回の私のケースでは、図の左側の曲げばねが切れる前に、違うところが壊れました。右のねじりばねが切れたことで、曲げばねが全く効かなくなり、可動支点は支点としての役目を果たさなくなっていました。この状況ではボタン部分が基盤側にぺったりくっついた状態になってしまいます。具体的には、力点の周りの丸い部分の右端、作用点と反対側が基盤にあたり、まずはここが新たな支点となって、支点、力点、作用点の順で一直線に並ぶことになります。しかし問題が一つあります。ストロークが非常に短いんです。
そもそも作用点のストロークが接点のストローク分しかないところに、力点が内側にありますので、力点を押せる量は微々たるものです。作用点のタブの根本あたりが少しでも変形してしまうと、もうスイッチを押すことが出来なくなってしまいます。更に、力点のカップ部分の下にはLEDが居ますので、少しでも何かが引っかかったり、角が挟まったりするとそれでもまた押せなくなってしまいます。仕方がないので今度はどこかに新たな支点となってくれるところはないかと、ボタン部分に横向きの力を加えながらぐりぐりと力点の周りのカップ部分のフチを探るように力を加えていくわけです。最初はボタンを作用点側に倒すことで割と簡単にスイッチが入ったと思います、しかし、このボタン、カップ状の部品の横っちょに平たい部品がぴっとくっついているだけの構造です。このカップ状の部分は3次元構造になっていますから構造的にとても強い作りになっているのに対し、タブの部分は、厚みがあるとは言ってもしょせん平面の部品です。力を掛ければ根元に応力が集中しますし、徐々に変形もしてきます。変形するとさらに強い力でボタンをこねくり回す必要が生じてくるので、さらに根元に力が加わり、ついに耐え切れなくなって破断した、というのが今回の故障のシナリオだったのだろうと考えています。
というか、もう、あんなやわいプラスチック部品オフセット荷重でひねりなんか入れたらダメだって・・・・
原因が分かったとことで、どうやって直すかですが、折れてしまった荷重伝達部品はもう治りません。交換部品も手に入りそうな気がしないので、とりあえずこのボタンでスイッチを入れることは諦めます。とにかく何らかの方法で基盤上のスイッチが押せればいい、と考えた結果、もう単純に、作用点の裏側のベゼルにドリルで穴をあけてそこからゼムクリップを伸ばした棒でスイッチを押す、ということにしました。CDの強制イジェクト穴方式です。
ただ、直接ゼムクリップで基盤を押すのはスイッチの寿命を縮めることにつながりかねないので、テープを使って折れたタブをあるべき位置に「配置」し、そのタブを裏からクリップで突っついて間接的にスイッチを押す方式としました。
組立途中の写真がこちら。まず電源ボタンの脇に穴をあけたところ。
そして、ビニールテープでタブを「配置」した所です。
ビニールテープにはよく見ると3つの穴が開いているのが見えると思います。向かって左側の穴は基盤のボルトでとも締めにするための穴、真ん中の穴は折れたタブのスイッチを押す部分についていたボッチ、右の穴はLEDの明り取り用の穴です。
組み立てる際は、ディスプレイの裏側の外枠を一旦外して裏返すと、リボン状の配線に余裕ができますので、この裏返した状態でベゼルに基盤を固定し、その後くるっとベゼルを反転させながら液晶を表に返してやったのちに外枠を嵌める、という手順になります。こちらが外枠を外したところ、
そしてこちらが、ベゼルに基盤を取り付けたところです。
これでくるっと裏返してベゼルを表側に回し、
外枠にベゼルをカチッと嵌めてやれば、工事は完了です。
あ、くれぐれも最初に外した4本のビスを付け直すのをお忘れなく。
こちらが、完成した電源ボタン横の電源スイッチ穴。
そして、この穴の奥をクリップでぽちっと押すと・・・
無事復活となりました☆
今回のお話は以上です。
今年もまた、とことん趣味に走ったこだわりネタを書いていきたいと思いますので、期待しないでお待ちください。
ではでは。
]]>
次はいよいよGoogle Playに登録か?と思わせておいて、この1週間やっていたことと言えば、サポート用ホームページの作成でした。
だって、これがアプリのパッケージ名になるわけなので、いつまでも「com.example.・・・」ではないだろう、と言う訳で。
とは言え、そもそものやりたいことからは外れますので、できるだけ簡単に、つるっと作りたいと思います。
そこで今回お手伝い頂いたのはこちらの本です。
またまたブックオフで買ってきました。
この本のサンプルのいいところは、スマートフォンサイトに対応していることです。それも、小難しいレスポンシブサイトではなく、PCサイト用とスマートフォンサイト用の2つのテンプレートを準備しておいて、ユーザエージェントに応じて切り替える方式なので、私のような頭の固いおじさんでもついていけます。
この本の中から適当なサンプルを1ついただいて、それをカスタマイズしてサイトを作ることにしました。
使わせていただいたのはこちらのサンプルです。
歯医者さんです。これを元に、いくつか変更を加えていきたいと思います。
・3カラム→2カラム構成に変更
・テーマカラーの変更
・ロゴの変更
・トップ画像の変更
・お問い合わせフォームの追加
最初の4項目に書いたような見た目の修正結果はこちらになります。
いい感じです。
スマートフォンサイトとPC用サイトを見分ける部分はこうなっています。
<script type="text/javascript"> if (document.referrer.indexOf('smart.html') == -1 && ((navigator.userAgent.indexOf('iPhone') > 0 && navigator.userAgent.indexOf('iPad') == -1) || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0)) { location.href = 'smart.html'; } </script>
スマートフォンサイトのインデックスページであるsmart.htmlから来た場合を除き、ユーザーエージェントがスマートフォン関係だった場合にはスマートフォン専用のインデックスページに飛ばす、という意味です。スマートフォンサイト側には「PCサイトを表示する」というボタンを付けていますので、このボタンから来た場合を除き、検索などから直接飛んできたような場合にはまずスマートフォンサイトを表示させるようにする、ということになります。
スマートフォンサイトからPCサイトを表示させた場合のみ、スマートフォンサイトに戻るボタンも表示させます。その仕組みはこちらです。
<div id="gotosmart"> <p><a href="smart.html">スマートフォンサイトへ</a></p> </div> <script type="text/javascript"> if (((navigator.userAgent.indexOf('iPhone') > 0 && navigator.userAgent.indexOf('iPad') == -1) || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0)) { document.getElementById("gotosmart").style.display = 'block'; } </script>
このid、gotosmartはcss側でdisplay="none"を指定してありますので、通常は見えません。これに対し上記のスクリプトで、スマートフォンで見た時のみdisplay="block"として表示させるようにしているわけです。
さて、先ほど挙げた変更点の最後、お問い合わせフォームを追加する、につきましては、こちらのスクリプトを使用させていただきました。
メールフォームプロ
非常に高機能なメールフォームで、正直このサイトに使うだけだったらこんなにたくさんの機能はいりません。今後その他のサイトで使うこともあるかも、と思って練習の意味も込めて今回このCGIを選びました。
というのは建前で、本当は機能がたくさんあって嬉しくなって入れちゃってから、使いきれてないかもと少し反省したという次第です。
メールフォームプロの設置方法は概略こんな感じです。
・コードをダウンロードして、解凍する。
・コードをサーバにアップロードする。(CGIが動作するフォルダが決まっているとちょっと面倒)
・指令書に従ってパーミッションを設定する。
・example.htmlにアクセスして、スクリプトの動作を確認する。
・config.cgiを修正して、各種設定を行う。
・example.htmlを修正して、お問い合わせフォームを作成する。
・thanks.htmlを修正して、お問い合わせいただきありがとうございましたページを作成する。
config.cgiの設定は、高機能なだけあって色々複雑ですが、楽しみながらいじっているうちに設定できてしまうくらいなものです。心配するほどの事ではありません。
以上で出来上がったサイトがこちらになります。
「てちくんのかんたんアプリ工場」
コンテンツはこれから充実させていきますが、とりあえずこれで受け皿が出来上がりました。
次回は・・・・内容未定です。お楽しみに。
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#77543a</color> <color name="colorPrimaryDark">#362111</color> <color name="colorAccent">#77543a</color> </resources>
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#77543a</color> <color name="colorPrimaryDark">#362111</color> <color name="colorAccent">#77543a</color> <color name="app_primary">#77543a</color> <color name="app_secondary">#77543a</color> </resources>
<resources> (中略) <style name="EditTextColorControl"> <item name="colorControlNormal">@color/app_primary</item> <item name="colorControlActivated">@color/app_secondary</item> <item name="colorControlHighlight">@color/app_secondary</item> </style> </resources>
(前略) <EditText android:layout_width="@dimen/inputWidth" android:layout_height="match_parent" android:inputType="numberDecimal" android:ems="10" android:id="@+id/editText" android:theme="@style/EditTextColorControl" android:textSize="@dimen/inputSize" /> (後略)
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.google.android.gms:play-services-ads:8.4.0' }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.tetsuya.unitconverter6"> <!-- Include required permissions for Google Mobile Ads to run--> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <!--This meta-data tag is required to use Google Play Services.--> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <activity android:name=".UnitConverter6"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--Include the AdActivity configChanges and theme. --> <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:theme="@android:style/Theme.Translucent" /> </application> </manifest>
<resources> <string name="app_name">UnitConverter</string> <string name="banner_ad_unit_id">ca-app-pub-3940256099942544/6300978111</string> <string name="categoryText">Category: </string>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:ads="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.tetsuya.unitconverter6.UnitConverter6"> (中略) <com.google.android.gms.ads.AdView android:id="@+id/adView" android:layout_width="wrap_content" android:layout_height="wrap_content" ads:adSize="BANNER" ads:adUnitId="@string/banner_ad_unit_id" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true"> </com.google.android.gms.ads.AdView> </RelativeLayout>
package com.example.tetsuya.unitconverter6; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.TextView; import android.view.View; import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView; import java.util.ArrayList; import android.text.Html; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdView; public class UnitConverter6 extends AppCompatActivity { (中略) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unit_converter6); (中略) AdView mAdView = (AdView) findViewById(R.id.adView); AdRequest adRequest = new AdRequest.Builder().build(); mAdView.loadAd(adRequest); } }
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 枠線付き長方形 --> <item> <shape android:shape="rectangle"> <solid android:color="#FAFAFA"/> <stroke android:width="1dp" android:color="#AAAAAA" /> </shape> </item> <!-- 1dp分の padding を設定した枠線なし長方形 --> <item android:bottom="1dp"> <shape android:shape="rectangle"> <solid android:color="#FAFAFA"/> </shape> </item> </layer-list>リスト中にコメントで書いてありますが、前半で枠付きの長方形を作ります。次に後半で枠無しの長方形を、下側に1dpのpaddingを持たせて重ねてやります。これで、隙間から1dpの下線が除いているイメージになります。
unitSpinnerInput.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) { idxi = unitSpinnerInput.getSelectedItemPosition(); commentArrayInput = new String[30]; if (categoryNumber==0) { // 長さ commentArrayInput = getResources().getStringArray(R.array.unitCommentLength); textView3.setText(commentArrayInput[idxi]); switch(idxi){ case 0: // m convRatioInput = 1.0; break; case 1: // km (以下省略)
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 入力欄に記入されたテキストを取得 input = editText.getText().toString(); // 取得したテキストを数値に変換 if (!input.equals("")) { inputValue = Double.parseDouble(input); } else { inputValue = 0; } if (categoryNumber==10) { // 角度の場合 if (idxi==6) { intermediateValue = Math.atan(inputValue/100); } else { intermediateValue = inputValue*convRatioInput; } if (idxo==6) { outputValue = 100*Math.tan(intermediateValue); } else { outputValue = intermediateValue/convRatioOutput; } } else if (categoryNumber==17) { // 温度の場合 switch (idxi){ case 0: intermediateValue = inputValue; break; case 1: intermediateValue = inputValue + 273.15; break; case 2: intermediateValue = (inputValue+459.67)/1.8; break; case 3: intermediateValue = inputValue/1.8; } switch (idxo) { case 0: outputValue = intermediateValue; break; case 1: outputValue = intermediateValue - 273.15; break; case 2: outputValue = intermediateValue*1.8 - 459.67; break; case 3: outputValue = intermediateValue*1.8; break; } } else { // その他のカテゴリーの場合 // 入力単位→出力単位に変換 outputValue = inputValue * convRatioInput / convRatioOutput; } // 変換した数値を文字列として出力エリアにセット textView2.setText(String.format("%.10g", outputValue)); } });
<string-array name="category"> <item>長さ<sup><small>2</small></sup></item> <item>面積</item> <item>体積</item> <item>重さ</item> </string-array>
String[] unitList; (中略) categoryNumber = categorySpinner.getSelectedItemPosition(); switch (categoryNumber) { case 0: // 長さ unitList = getResources().getStringArray(R.array.unitListLength); break; case 1: // 面積 unitList = getResources().getStringArray(R.array.unitListArea); break; case 2: // 体積 unitList = getResources().getStringArray(R.array.unitListVolume); break; case 3: // 重さ unitList = getResources().getStringArray(R.array.unitListWeight); break; } adapter = new ArrayAdapter(getApplicationContext(),android.R.layout.simple_spinner_item, unitList); unitSpinnerInput.setAdapter(adapter); unitSpinnerOutput.setAdapter(adapter);単位リストを入れる配列「unitList」を冒頭で「String[]」で宣言していますが、これは6,9,12,15行目のgetResources().getStringArrayがstring[]しか受け付けてくれないためです。htmlタグ付きのStringはただのStringではなく「CharSequence」と呼ばれるものになるので、このやり方では通らなかったということでした。
@Override public void onItemSelected(AdapterView parent, View view, int position, long id) { categoryNumber = categorySpinner.getSelectedItemPosition(); unitList = new ArrayList<>(); switch (categoryNumber) { case 0: // 長さ unitList.add("m"); unitList.add("km"); unitList.add("mile"); break; case 1: // 面積 unitList.add(Html.fromHtml("m<sup><small>2</small></sup>")); unitList.add("a"); unitList.add("ha"); break; case 2: // 体積 unitList.add(Html.fromHtml("m<sup><small>3</small></sup>")); unitList.add("cc"); unitList.add("L"); break; case 3: // 重さ unitList.add("kg"); unitList.add("lb"); unitList.add("貫"); break; } adapter = new ArrayAdapter(getApplicationContext(),R.layout.spinner_item, unitList); unitSpinnerInput.setAdapter(adapter); unitSpinnerOutput.setAdapter(adapter); convRatioInput = 1.0; convRatioOutput = 1.0; }ポイントは4行目でunitListを確保し、12行目と17行目でHtml.fromHtml()メソッドでタグを記入しているところです。こうしてやることで、切り替えたスピナーでも上付き文字を表示することができました。
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:spinnerItemStyle">@style/SpinnerItemStyle</item> <item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItemStyle</item> </style> <style name="SpinnerItemStyle" parent="android:Widget.Holo.Light.TextView.SpinnerItem"> <item name="android:textSize">24sp</item> <item name="android:textColor">#000000</item> </style> <style name="SpinnerDropDownItemStyle" parent="android:Widget.Holo.Light.DropDownItem"> <item name="android:textSize">24sp</item> <item name="android:textColor">#000000</item> </style> </resources>
adapter = new ArrayAdapter(getApplicationContext(),R.layout.spinner_item, unitList);
adapter = new ArrayAdapter(getApplicationContext(),android.R.layout.simple_spinner_item, unitList);
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24sp" android:gravity="left" android:textColor="#000000" android:padding="5dp" />こんな形に、文字サイズと文字色、パディング等を指定しています。
<resources> <string name="app_name">UnitConverter4</string> <string name="categoryText">カテゴリー:</string> <string name="initialValue">0.0</string> <string name="convert">変換</string> <string-array name="category"> <item>長さ</item> <item>面積</item> <item>体積</item> <item>重さ</item> </string-array> <string-array name="unitListLength"> <item>m</item> <item>km</item> <item>mile</item> </string-array> <string-array name="unitListArea"> <item>m2</item> <item>a</item> <item>ha</item> </string-array> <string-array name="unitListVolume"> <item>m3</item> <item>cc</item> <item>L</item> </string-array> <string-array name="unitListWeight"> <item>kg</item> <item>lb</item> <item>貫</item> </string-array> </resources>
package com.example.tetsuya.unitconverter4; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; // 中で使用するEditText, TextView, Viewをimport import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.TextView; import android.view.View; import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView; public class UnitConverter4 extends AppCompatActivity { // 使用する変数等を定義 EditText editText; TextView textView2; double convRatioInput = 1.0; double convRatioOutput = 1.0; double inputValue = 0.0; double outputValue = 0.0; int categoryNumber = 0; String input; String[] unitList; Spinner categorySpinner; Spinner unitSpinnerInput; Spinner unitSpinnerOutput; ArrayAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unit_converter4); // 入力エリアと出力表示エリアのインスタンスを取得 editText = (EditText) findViewById(R.id.editText); // 入力エリア textView2 = (TextView) findViewById(R.id.textView2); // 出力エリア categorySpinner = (Spinner) findViewById(R.id.spinner); // カテゴリースピナー unitSpinnerInput = (Spinner) findViewById(R.id.spinner2); // 入力単位スピナー unitSpinnerOutput = (Spinner) findViewById(R.id.spinner3); // 出力単位スピナー // 変換ボタンのオンクリックリスナーを設定 findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // ボタンクリック時の処理を定義 // 入力欄に記入されたテキストを取得 input = editText.getText().toString(); // 取得したテキストを数値に変換 if (!input.equals("")) { inputValue = Double.parseDouble(input); } else { inputValue = 0; } // 入力単位→出力単位に変換 outputValue = inputValue * convRatioInput / convRatioOutput; // 変換した数値を文字列として出力エリアにセット textView2.setText(String.format("%.10g", outputValue)); } }); // 入力単位spinnerのアイテムセレクトリスナーを設定 // リスナーを登録 unitSpinnerInput.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) { int idx = unitSpinnerInput.getSelectedItemPosition(); if (categoryNumber==0) { // 長さ switch(idx){ case 0: // m convRatioInput = 1.0; break; case 1: // km convRatioInput = 1000.0; break; case 2: // mile convRatioInput = 1609.334; break; } }else if(categoryNumber==1){ // 面積 switch(idx){ case 0: // m2 convRatioInput = 1.0; break; case 1: // a convRatioInput = 100.0; break; case 2: // ha convRatioInput = 10000.0; break; } }else if(categoryNumber==2){ // 体積 switch(idx){ case 0: // m3 convRatioInput = 1.0; break; case 1: // cc convRatioInput = 0.000001; break; case 2: // L convRatioInput = 0.001; break; } }else if(categoryNumber==3){ // 重さ switch (idx) { case 0: // kg convRatioInput = 1.0; break; case 1: // lb convRatioInput = 0.45359243; break; case 2: // 貫 convRatioInput = 3.75; break; } } } // アイテムが選択されなかった public void onNothingSelected(AdapterView<?> parent) { } }); // 出力単位spinnerのアイテムセレクトリスナーを設定 // リスナーを登録 unitSpinnerOutput.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) { int idx = unitSpinnerOutput.getSelectedItemPosition(); if (categoryNumber==0) { // 長さ switch(idx){ case 0: // m convRatioOutput = 1.0; break; case 1: // km convRatioOutput = 1000.0; break; case 2: // mile convRatioOutput = 1609.334; break; } }else if(categoryNumber==1){ // 面積 switch(idx){ case 0: // m2 convRatioOutput = 1.0; break; case 1: // a convRatioOutput = 100.0; break; case 2: // ha convRatioOutput = 10000.0; break; } }else if(categoryNumber==2){ // 体積 switch(idx){ case 0: // m3 convRatioOutput = 1.0; break; case 1: // cc convRatioOutput = 0.000001; break; case 2: // L convRatioOutput = 0.001; break; } }else if(categoryNumber==3){ // 重さ switch (idx) { case 0: // kg convRatioOutput = 1.0; break; case 1: // lb convRatioOutput = 0.45359243; break; case 2: // 貫 convRatioOutput = 3.75; break; } } } // アイテムが選択されなかった public void onNothingSelected(AdapterView<?> parent) { } }); // カテゴリーspinnerのアイテムセレクトリスナーを設定 // リスナーを登録 categorySpinner.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { categoryNumber = categorySpinner.getSelectedItemPosition(); switch (categoryNumber) { case 0: // 長さ unitList = getResources().getStringArray(R.array.unitListLength); break; case 1: // 面積 unitList = getResources().getStringArray(R.array.unitListArea); break; case 2: // 体積 unitList = getResources().getStringArray(R.array.unitListVolume); break; case 3: // 重さ unitList = getResources().getStringArray(R.array.unitListWeight); break; } adapter = new ArrayAdapter(getApplicationContext(),android.R.layout.simple_spinner_item, unitList); unitSpinnerInput.setAdapter(adapter); unitSpinnerOutput.setAdapter(adapter); convRatioInput = 1.0; convRatioOutput = 1.0; } // アイテムが選択されなかったとき @Override public void onNothingSelected(AdapterView<?> parent) { } }); } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.tetsuya.unitconverter3.UnitConverter3"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:weightSum="1" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:id="@+id/linearLayout"> <EditText android:layout_width="@dimen/ioWidth" android:layout_height="wrap_content" android:inputType="numberDecimal" android:ems="10" android:id="@+id/editText" /> <Spinner android:layout_width="@dimen/unitWidth" android:layout_height="wrap_content" android:id="@+id/spinner" android:entries="@array/unit" android:spinnerMode="dropdown" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/linearLayout" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/linearLayout2"> <TextView android:layout_width="@dimen/ioWidth" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/zero" android:id="@+id/textView" /> <Spinner android:layout_width="@dimen/unitWidth" android:layout_height="wrap_content" android:id="@+id/spinner2" android:entries="@array/unit" android:spinnerMode="dropdown" /> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/convert" android:id="@+id/button" android:layout_below="@+id/linearLayout2" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> </RelativeLayout>
<resources> <string name="app_name">UnitConverter3</string> <string name="convert">変換</string> <string name="zero">0.0</string> <string-array name="unit"> <item>kg</item> <item>lb</item> <item>貫</item> </string-array> </resources>
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <dimen name="unitWidth">120dp</dimen> <dimen name="ioWidth">220dp</dimen> </resources>
package com.example.tetsuya.unitconverter3; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; // 中で使用するEditText, TextView, Viewをimport import android.widget.EditText; import android.widget.TextView; import android.view.View; import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView; public class UnitConverter3 extends AppCompatActivity { // 使用する変数等を定義 EditText editText; TextView textView; double convRatioInput = 1.0; double convRatioOutput = 1.0; double inputValue = 0.0; double outputValue = 0.0; String input; Spinner unitSpinnerInput; Spinner unitSpinnerOutput; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unit_converter3); // 入力エリアと出力表示エリアのインスタンスを取得 editText = (EditText) findViewById(R.id.editText); // 入力エリア textView = (TextView) findViewById(R.id.textView); // 出力エリア unitSpinnerInput = (Spinner) findViewById(R.id.spinner); // 入力単位スピナー unitSpinnerOutput = (Spinner) findViewById(R.id.spinner2); // 出力単位スピナー // 変換ボタンのオンクリックリスナーを設定 findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // ボタンクリック時の処理を定義 // 入力欄に記入されたテキストを取得 input = editText.getText().toString(); // 取得したテキストを数値に変換 if (!input.equals("")){ inputValue = Double.parseDouble(input); }else{ inputValue = 0; } // 入力単位→出力単位に変換 outputValue = inputValue * convRatioInput / convRatioOutput; // 変換した数値を文字列として出力エリアにセット textView.setText(String.format("%.10g",outputValue)); } }); // 入力単位spinnerのアイテムセレクトリスナーを設定 // リスナーを登録 unitSpinnerInput.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) { int idx = unitSpinnerInput.getSelectedItemPosition(); switch(idx){ case 0: // kg convRatioInput = 1.0; break; case 1: // lb convRatioInput = 0.45359243; break; case 2: // 貫 convRatioInput = 3.75; break; } } // アイテムが選択されなかった public void onNothingSelected(AdapterView<?> parent) { } }); // 出力単位spinnerのアイテムセレクトリスナーを設定 // リスナーを登録 unitSpinnerOutput.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) { int idx = unitSpinnerOutput.getSelectedItemPosition(); switch(idx){ case 0: // kg convRatioOutput = 1.0; break; case 1: // lb convRatioOutput = 0.45359243; break; case 2: // 貫 convRatioOutput = 3.75; break; } } // アイテムが選択されなかった public void onNothingSelected(AdapterView<?> parent) { } }); } }
<resources> <string name="app_name">UnitConverter2</string> <string name="input">入力:</string> <string name="inputUnit">lb</string> <string name="output">出力:</string> <string name="initialOutput">0.0</string> <string name="outputUnit">kg</string> <string name="convert">変換</string> <string name="unit1">lb</string> <string-array name="menu"> <item>lb → kg</item> <item>kg → lb</item> </string-array> </resources>
package com.example.tetsuya.unitconverter2; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; // 中で使用するEditText, TextView, Viewをimport import android.widget.EditText; import android.widget.TextView; import android.view.View; import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView; public class UnitConverter2 extends AppCompatActivity { // 使用する変数等を定義 EditText editText; TextView textView4; TextView textView2; TextView textView5; double conversionRatio = 0.45359243; // lbs→kgの変換係数を初期値に double inputValue = 0; double outputValue = 0; String input; Spinner menuSpinner; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unit_converter2); // 入力エリアと出力表示エリアのインスタンスを取得 editText = (EditText) findViewById(R.id.editText); // 入力エリア textView4 = (TextView) findViewById(R.id.textView4); // 出力エリア textView2 = (TextView) findViewById(R.id.textView2); // 入力側単位表示 textView5 = (TextView) findViewById(R.id.textView5); // 出力側単位表示 menuSpinner = (Spinner) findViewById(R.id.spinner); // メニュースピナー // 変換ボタンのオンクリックリスナーを設定 findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // ボタンクリック時の処理を定義 // 入力欄に記入されたテキストを取得 input = editText.getText().toString(); // 取得したテキストを数値に変換 if (!input.equals("")){ inputValue = Double.parseDouble(input); }else{ inputValue = 0; } // 入力単位→出力単位に変換 outputValue = inputValue * conversionRatio; // 変換した数値を文字列として出力エリアにセット textView4.setText(String.valueOf(outputValue)); } }); // spinnerのアイテムセレクトリスナーを設定 // リスナーを登録 menuSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { // アイテムが選択された時 public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) { int idx = menuSpinner.getSelectedItemPosition(); switch(idx){ case 0: conversionRatio = 0.45359243; textView2.setText(R.string.inputUnit); textView5.setText(R.string.outputUnit); break; case 1: conversionRatio = 2.20462233; textView2.setText(R.string.outputUnit); textView5.setText(R.string.inputUnit); break; } } // アイテムが選択されなかった public void onNothingSelected(AdapterView<?> parent) { } }); } }前回から変わった部分を解説します。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.tetsuya.unitconverter1.UnitConverter1"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/linearLayout"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/input" android:id="@+id/textView" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="numberDecimal" android:ems="10" android:id="@+id/editText" android:layout_weight="1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/lbs" android:id="@+id/textView2" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/linearLayout" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:weightSum="1" android:id="@+id/linearLayout2"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/output" android:id="@+id/textView3" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/initialValue" android:id="@+id/textView4" android:layout_weight="0.99" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/kg" android:id="@+id/textView5" /> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/convert" android:id="@+id/button" android:layout_below="@+id/linearLayout2" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> </RelativeLayout>
<resources> <string name="app_name">UnitConverter1</string> <string name="input">入力:</string> <string name="lbs">lbs</string> <string name="output">出力:</string> <string name="initialValue">0</string> <string name="kg">kg</string> <string name="convert">変換</string> </resources>
package com.example.tetsuya.unitconverter1; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; // 中で使用するEditText, TextView, Viewをimport import android.widget.EditText; import android.widget.TextView; import android.view.View; public class UnitConverter1 extends AppCompatActivity { // 使用する変数等を定義 EditText editText; TextView textView4; double conversionRatio=0.45359243; // lbs→kgの変換係数 double inputValue; double outputValue; String input; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unit_converter1); // 入力エリアと出力表示エリアのインスタンスを取得 editText = (EditText) findViewById(R.id.editText); textView4 = (TextView) findViewById(R.id.textView4); // 変換ボタンのオンクリックリスナーを設定 findViewById(R.id.button).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ // ボタンクリック時の処理を定義 // 入力欄に記入されたテキストを取得 input = editText.getText().toString(); // 取得したテキストを数値に変換 inputValue = Double.parseDouble(input); // lbs→kgに変換 outputValue = inputValue*conversionRatio; // 変換した数値を文字列として出力エリアにセット textView4.setText(String.valueOf(outputValue)); } }); } }