- 投稿日:2019-04-13T22:54:57+09:00
Textboxの入力制限について
Android開発をしている中で、テキストボックスに制限を追加したいことはありませんか?
今回は入力値を選択して、編集できないようにする制限です。
その中で試したことをメモとして残したいと思います。実現したいこと
テキストボックスを押すと日付のカレンダーが出て、日にちを選択するとテキストボックスに表示されるようにしました。
それ自体はすぐにできましたが、入力して、日にちが変更できてしまうことがネックと言いますか、要件としてはダメだし、後の処理でエラーが発生する可能性大なので、編集できないようにしたいと思いました。試したこと
①isEnableとisCursorVisibleの併用
調べてみるとisCursorVisibleをfalseに設定して、isEnableをtrueに設定すると、カーソルが合わないということがわかり、下記のソースを追加しました。dateText.isCursorVisible = false dateText.isEnabled = trueこれだと確かにカーソルは合わないですが、キーボードが表示されていると入力できてしまいました。
なので、追加で、キーボードが非表示になる処理か、編集できないようにする必要があるようです。②isFocusableの使用
さらに追加で調べてみるとisFocusableでフォーカスが当たらないようにできることがわかり、こちらに書き換えました
dateText.isFocusable= falseテキストボックスが押せるのか不安はありましたが、試してみると編集はできず、日時が選択できるようにできました。
少し時間はかかりましたが、試行錯誤することはやっぱり大切ですね。
- 投稿日:2019-04-13T20:17:34+09:00
Keindahan Air Terjun Bojonekoneng
Pada kesempatan yang baik ini kami admin agen sbobet akan memberikan informasi menarik tentang Air Terjun yang ada di Kabupaten Bogor. Jika dalam wkatu dekat Anda ingin merencanakan liburan bersama keluarga, ada baiknya menyimak artikel berikut ini mungkin akan masuk dalam checklist Anda.
Air Terjun Bojongkoneng terletak di wilayah Bogor, tepatnya di Desa Bojongkoneng, Sukaraja. Tempat tersebut diapit oelh 2 buah gunung, yaitu Gunung Batu dan Gunung Geulis. Untuk mencapai kesana tidaklah mudah. Minimnya informasi seputar objek wisata ini membuat Anda lebih banyak bertanya kepada penduduk setempat jika tidak ingin salah jalan. Belum lagi kondisi jalan yang tidak sesuai dengan isi pamflet promosi yang disebarkan. Menurut salah seorang pengunjung yang pernah datang ke sana, jalan beraspal rupanya bersambung dengan jalan bebatuan yang tidak nyaman dan dapat dikatakan sempit sehingga tidak muat jika dua kendaraan roda empat sampai bersisian. Salah satu dari kendaraan harus mengalah ke pinggir dan membiarkan kendaraan dari arah lain lewat lebih dulu.
Setelah sampai di jalan yang benar-benar sempit, perjalanan kemudian dilanjutkan dengan berjalan kaki, melewati jalan setapak yang di kanan dan kirinya terdapat kebun singkong milik penduduk. Pengunjung juga harus melintasi sungai dan pematang sawah. Sungguh petualangan yang mengasyikkan bagi para pencinta alam tentunya.Bebrapa meter setelahnya, tampaklah air terjun di kejauhan. Saking besarnya, pengunjung dapat melihat dengan jelas. Kira-kira tingginya 30 meter dan pengunjung bisa merasakan hembusan angin yang cukup kencang bersamaan dengan butiran air. Bagi para pecinta fotografi perlu mengantisipasi kamera dalam proses mengambil gambar sebab butiran air akan terbawa angin hingga cukup jauh dan mengenai lensa. Carilah posisi yang benar-benar nyaman agar mendapatkan gambar yang maksimal tanpa perlu berkali-kali mengelap lensa.
Air Terjun Bojongkoneng dikelilingi bukit terjal dan menyisakan celah di sisi kiri dan air mengalir melewatinya. Dari situlah pengunjung masuk mendekati objek yang dimaksudkan.
Anda tidak perlu berpikir panjang untuk merasakan kesegaran dari air terjun ini. Rasa lelah maupun pikiran yang penat akan terlupakan begitu saja, ketika Anda berenang-renang sembari mencoba mendekati pusat curahan air. Anda butuh usaha keras untuk sampai di sana karena debit air yang besar sepertinya bukan tandingan yang seimbang untuk Anda. Tapi, jika Anda bersikeras, tentunya Anda juga akan dapat sampai di sana. Percayalah!
Setelah puas basah-basahan, Anda bisa meluangkan waktu sejenak untuk menikmati pemandangan alam yang benar-benar indah. Masih alami dan jauh dari sampah-sampah ydng di buang sembarangan tempat. Selain itu, menurut cerita penduduk, di sekitar air terjun ini pun juga merupakan habitat monyet. Jika Anda sedang beruntung, tentu Anda dapat melihat hewan-hewan tersebut berkeliaran. Tapi awasi barang-barang Anda agar tidak disambar oleh mereka. Selamat berkunjung di Air Terjun Bojongkoneng.
Mungkin begitulah kira-kira pengalaman pribadi kami agen sbobet rasakan saat berkunjung ke sana. Cobalah, untuk merasakan sensasi berpetualang melintasi hutan untuk menemukan air terjun yang tersembunyi.
- 投稿日:2019-04-13T19:36:07+09:00
iOSアプリエンジニアのためのAndroidアプリ開発入門 その1 〜インストール編〜
はじめに(対象読者と内容の方向性)
iOSアプリ開発を5年ほどやっていますが、諸事情によりAndroidアプリ開発にも挑戦することになりました。
せっかくなので、わたしと同じように『iOSアプリ開発はやったことあるけど、Androidアプリ開発ははじめて』という方向けにAndroidアプリ開発についてまとめていきます。iOSアプリエンジニア向けなので、『iOSでのこういう機能は、Androidではこうやって実装する』、『iOSではこういう考え方だけど、Androidではこういう考え方で実装する』みたいな形で紹介できればと考えています。
免責事項
Androidアプリ開発初心者が勉強しながら書いているので、たぶん間違いがたくさんあります。勉強していく過程で間違いに気がついたらその都度修正をしますが、「ここ間違ってるで〜」というのがあれば、ぜひツッコンでください。
全体の目次
その1 〜インストール編〜 ←イマココ
その2 〜新規プロジェクト作成編〜
その3 〜エミュレータ編〜Android Studioのインストール
まずは、iOSアプリ開発でのXcodeに当たる、Android Studioをインストールします。
Xcodeと同じようにけっこう容量が大きいので、それなりの回線で時間があるときに実行しましょう。こちら↓のDeveloperサイトにアクセスして、DOWNLOAD ANDROID STUDIOボタンをクリックします。
Android Studio利用規約の確認画面が表示されるので、内容を確認して同意にチェックを入れて、ダウンロードボタンをクリックします。
ダウンロードされたファイルをダブルクリックします。
Android StudioをApplicationsフォルダにコピーします。
Android Studioを起動します。
開いてもよろしいですか? と聞かれるので、開くボタンをクリックします。
『Import Android Studio settings from:』と聞かれますが、はじめてのインストールで設定ファイルはないので、『Do not import settings』を選択してOKボタンをクリックします。
改善のためのデータ送信を許可するか聞かれるので、開発者として協力するために『Send usage statistics to Google』ボタンをクリックします(データを送りたくない場合は『Don't send』ボタンをクリックしてください)。
Welcome画面が表示されました。ありがとうございます。
Nextボタンをクリックすると、インストールタイプを聞かれます。はじめてでカスタムする内容もわからないので、Standardを選択してNextボタンをクリックします。
テーマの選択が表示されるので、DarculaかLightのどちらかを選択します。最近はやりのダークテーマっぽいDarculaにしてみました。
インストール内容の確認が表示されるので、内容を確認してFinishボタンをクリックします。
データのダウンロードがはじまります。
セキュリティの警告が表示されるので、セキュリティとプライバシーを開いて、許可ボタンをクリックします。
インストールが終わったら、Finishボタンをクリックします。
Welcome画面が表示されました。XcodeのWelcome画面のように、プロジェクトの作成やプロジェクトを開くことができます。
終わりに
今回はここまでです。
次回の更新をお待ちください。
- 投稿日:2019-04-13T18:34:28+09:00
1行もコードを書かずにネイティブアプリ(もどき)をリリースする7つのステップ
前提
これだけでちゃんとしたアプリが作れるとは言いませんし、ネイティブアプリオワタとは言いません。
ただ、ノーコードでアプリをデプロイまでできるのは結構すごいなあと思ったので、共有します。
(やはりY Combinatorすごい)必要とされる知識など
- インターネット接続できる環境にあること。
- PCで画面をみれて、スプレッドシートが開けること。(&作れること)
- Gmailのアカウントがあること。
- 作りたいアプリのイメージがあること。
今回のアプリについて
米国株の配当金、買い時の指標などを管理できるアプリを作ります。
完成イメージは
メインページがこれで
詳細画面がこれです。シンプルですね。
もう一度言いますが、一行もコードは書いていません。
もう一つ付け加えると15分くらいでリリースまでこぎつけました。
では、作っていきましょう!
事前準備
手順1
Glideにアクセスする。
手順2
Create an appを押して、下記の画像の画面に遷移する
Sign Upを押して、Gmailのアカウントでログインする。
手順3
手順4
スプレッドシートを読み込む。
(スプレッドシートは事前に作っておいたものを利用)
僕の場合はここに書いてある「配当金管理」というスプレッドシートを使います。手順5
アプリの開発画面になったので、見た目を調整する
検索バーがデフォルトでついてて驚愕・・・
大まかにいうと、左側が「どんなことをしたいか」右側が「その詳細を変更する」という感じになっています。めっちゃわかりやすいですね。
機能は色々いじりながら試していってもらいたいのですが、先ほどの見た目に近づけるための方法を簡単に記載します。
まず、「ア」とか「ウ」とか左側に表示されるのがダサいので無くします。
Show initials as default Imageの部分が有効になっているので無効になります。次に色を黒くしたいので、左側のSettingsを押して、右側に出てくるThemeを押します。
これでほぼできたので、あとは細かいところを適当に作ります。(アイコンとか、色合いとかはご自身でどうぞ)
手順6
URLを決める。
Settingを押した後の画面でAPP URLを入れるところがあるので、適当に名前を決めて入力します。
手順7
リリースする(まじか・・・!)
左下のopen appを押す。
これでアプリができてしまいました。。
完成品がこれです。
PWA対応もしているので、Androidだともはやネイティブアプリです。
ちなみにiOSでもちゃんとアプリという認識で立ち上がってくれました。すごい世界がやってきたものだ。。
- 投稿日:2019-04-13T17:32:46+09:00
【Android】Google MapのinfoWindowにウェブ上の画像を表示する
1.プロジェクト作成
新規プロジェクトを作成します。
Google Maps Activityを選択し、プロジェクト名を入力して進みます。
自動的に生成されるres/values/google_maps_api.xmlのYOUR_KEY_HEREの部分を、取得してある自身のAPIキーで置き換えておきます。google_maps_api.xml<resources> <!-- 略 --> <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string> </resources>この時点で一度プログラムを起動し、地図がちゃんと表示される事を確認します。
2.レイアウトファイルを記述する
infoWindow用のレイアウトを作成します。今回はLinearLayoutにImageViewが一つあるだけのシンプルなものにします。
info_window_layout.xml<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>3.InfoWindowAdapterの記述
MapsActivity.javaのonMapReadyメソッドにて、InfoWindowAdapterを実装します。
MapsActivity.java@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // 〜略〜 mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { Marker lastMarker; View infoWindow; @Override public View getInfoWindow(Marker marker) { return null; } @Override public View getInfoContents(Marker marker) { // 今回はこちらに処理を記述 return null; } });infoWindowAdapterはgetInfoWindow()メソッドとgetInfoContents()メソッドの両方をオーバーライドする必要があり、かつどちらかに処理を記述しもう片方はnullを返す必要があります。今回はgetInfoContents()に処理を記述します。また、処理の都合上必要な変数lastMarkerとinfoWindowをinfoWindowAdapterのクラス内で宣言しておきます。
4.getInfoContents()メソッドの記述
@Override public View getInfoContents(Marker marker) { if(lastMarker==null || !lastMarker.equals(marker)){ lastMarker = marker; infoWindow = getLayoutInflater().inflate(R.layout.info_window_layout,null); ImageView img = infoWindow.findViewById(R.id.img); new DownloadImageTask(img,marker).execute(imgUrl); // ↑このあと実装 } return infoWindow; }最後まで実装してから細かく処理を追えばわかることですが、マーカーをクリックしてinfoWindowを表示させようとするとgetInfoWindow()メソッドは合計2回呼ばれることになります。1回目で画像をダウンロードする処理が走り、2回目はreturn infoWindow;だけ実行され、無限ループにならないようにしています。
5.画像のダウンロード処理のクラスを記述
private class DownloadImageTask extends AsyncTask<String,Void, Bitmap>{ ImageView img = null; Marker marker = null; DownloadImageTask(ImageView img, Marker marker){ this.img = img; this.marker = marker; } @Override protected Bitmap doInBackground(String... strings) { Bitmap bmp = null; try{ String urlStr = strings[0]; URL url = new URL(urlStr); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod("GET"); con.connect(); int resp = con.getResponseCode(); switch (resp){ case HttpURLConnection.HTTP_OK: InputStream is = con.getInputStream(); bmp = BitmapFactory.decodeStream(is); is.close(); break; default: break; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bmp; } @Override protected void onPostExecute(Bitmap bmp){ img.setImageBitmap(bmp); marker.showInfoWindow(); } }画像のダウンロード処理のクラスであるDownladImageTaskを記述します。画像のダウンロードは非同期で行う必要があるのでAsyncTaskを継承しています。画像のURLは、execute()で呼び出すときにStringで受け渡し、doInbackground()のstrings[0]で受け取ります。画像のダウンロードが完了したあとで呼ばれるonPostExecute()でImageViewに画像をセットしており、そのあとmarker.showInfoWindow()を呼ぶことでinfoWindowに画像が表示されます。
6.MapsActivity.javaの全体
マーカーはデフォルトの位置であるシドニー、画像は、ウェブ版のGoogle mapでシドニーで検索したときに出たもののurlを指定しています。
MapsActivity.javapackage com.example.test; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { private GoogleMap mMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); // Obtain the SupportMapFragment and get notified when the map is ready to be used. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; final String imgUrl = "https://lh5.googleusercontent.com/p/AF1QipNUrZvzjGohRsYfuwIpCS2MjYdAq_3xruYM5imS=w408-h271-k-no"; // Add a marker in Sydney and move the camera LatLng sydney = new LatLng(-34, 151); mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { Marker lastMarker; View infoWindow; @Override public View getInfoWindow(Marker marker) { return null; } @Override public View getInfoContents(Marker marker) { if(lastMarker==null || !lastMarker.equals(marker)){ lastMarker = marker; infoWindow = getLayoutInflater().inflate(R.layout.info_window_layout,null); ImageView img = infoWindow.findViewById(R.id.img); new DownloadImageTask(img,marker).execute(imgUrl); } return infoWindow; } }); } private class DownloadImageTask extends AsyncTask<String,Void, Bitmap>{ ImageView img = null; Marker marker = null; DownloadImageTask(ImageView img, Marker marker){ this.img = img; this.marker = marker; } @Override protected Bitmap doInBackground(String... strings) { Bitmap bmp = null; try{ String urlStr = strings[0]; URL url = new URL(urlStr); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod("GET"); con.connect(); int resp = con.getResponseCode(); switch (resp){ case HttpURLConnection.HTTP_OK: InputStream is = con.getInputStream(); bmp = BitmapFactory.decodeStream(is); is.close(); break; default: break; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bmp; } @Override protected void onPostExecute(Bitmap bmp){ img.setImageBitmap(bmp); marker.showInfoWindow(); } } }参考
https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.InfoWindowAdapter
https://stackoverflow.com/questions/36335004/how-to-get-image-in-infowindow-on-google-maps-with-picasso-android
- 投稿日:2019-04-13T10:04:02+09:00
KotlinでUTC標準記述の文字列を、日本時刻に変換して文字列出力
KotlinでAndroidアプリを作っていて、WebのAPIで返ってきたUTC標準時刻で記載された文字列の日時を、日本時刻に変換して表示する方法。
文字列をDateに、Dateを文字列に、というあたりの情報は結構見つかったのですが、TimeZoneを変更して出力するというやり方は「これ」というのが見当たらず、いくつかのページを参考に試行錯誤したらできたんですが自分で忘れそうなので備忘録です。やったこと
以下の手順で処理したらできました。
- UTCで書かれた文字列(私が扱っていた元データはISO8601形式だったので "yyyy-MM-dd'T'HH:m m:ssZ" でした(mmの間は本来くっついてます。markdownで勝手に変換されてしまうのを止める方法がわからなかった…orz))を、Dateに変換
- DateをCalendarに変換
- CalendarにTimezoneをセット
- DateFormatを指定して、文字列を出力
実際のソースコードはこちら
import android.text.format.DateFormat import android.icu.text.SimpleDateFormat import java.util.* val df = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") val jpCal:Calendar = Calendar.getInstance() jpCal.time = df.parse(item.updateDateTime) jpCal.timeZone = TimeZone.getTimeZone("Asia/Tokyo") holder.mUpdateDTView.text = DateFormat.format("MM-dd HH:mm",jpCal)item.updateDateTime内に、例えば
2019-04-12T01:00:00Zという文字列が設定されているとして、これでmUpdateDTView.textの中には04-12 09:00という文字列が出力されるようになりました。多分ですが、
"Asia/Tokyo"のところを、端末の標準設定とか持ってこれれば、APIから返ってきた時刻を、その端末の現地時間に合わせて表示できるんじゃないのかなと思います。(未検証ですが…)若干冗長な気はしているので、もっと簡単にできるよ~という方法があったら是非教えて頂きたいです。m(__)m
参考にさせていただいたサイト
https://developer.android.com/reference/android/text/format/DateFormat.html
https://qiita.com/emboss369/items/5a3ddea301cbf79d971a
https://stackoverflow.com/questions/48838992/how-to-convert-date-string-to-timestamp-in-kotlin



























