SQLの窓 イラストAC フリー素材

2017年10月29日

Android のメニュー項目を条件が満たされた時のみ利用可能にする / onPrepareOptionsMenu

ちょっと検索しても出てこなかったのですが、onPrepareOptionsMenu が、メニューが表示される直前に実行されます。なので、最初に Disable にして、条件が合えば Enable にするという処理です。

▼ Android Studio での デザイン表示


▼ エミュレータでの表示


	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {

		Log.i("lightbox","onPrepareOptionsMenu");

		menu.findItem(R.id.action_3).setEnabled(false);
		menu.findItem(R.id.action_4).setEnabled(false);
		menu.findItem(R.id.action_5).setEnabled(false);

		// 第二画面
		if ( helper.viewSwitcher.getDisplayedChild() == 1 ) {
			// 主キーが TextView で表示されているという事は、修正処理
			if (helper.getTextView(R.id.textViewCode).getVisibility() == View.VISIBLE) {
				// 削除処理以降を使用可能にする
				menu.findItem(R.id.action_3).setEnabled(true);
				menu.findItem(R.id.action_4).setEnabled(true);
				menu.findItem(R.id.action_5).setEnabled(true);
			}
		}

		return super.onPrepareOptionsMenu(menu);
	}




posted by at 2017-10-29 22:23 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2017年07月02日

Android Studio : LiveDoor のお天気情報をリストビューに表示した後、第二画面で name を変更して第一画面で再表示する手順

Android Studio : LiveDoor のお天気情報をリストビューに表示する手順 から続いている処理です


Intent でデータを送れるように、クラスを変更

Serializable インタフェース を追加
import java.io.Serializable;

public class WebData implements Serializable {

	String link;
	String name;

	@Override
	public String toString() {
		return name;
	}
}


Activity を追加して画面作成
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main2Activity">
    <Button
        android:id="@+id/buttonReturn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="戻る" />

    <TextView
        android:id="@+id/textViewLink"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="TextView"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/textViewName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="6dp"
        android:text="TextView"
        android:textSize="30sp"/>

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:textSize="30sp"/>

    <Button
        android:id="@+id/buttonUpdate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="更新"
        android:textSize="20sp"/>

</LinearLayout>


ListView に イベント処理を追加

選択した位置を保存する為に private int position; を定義
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

				// 行データを取得
				ArrayAdapter<WebData> arrayAdapter = (ArrayAdapter<WebData>) parent.getAdapter();
				WebData webData = arrayAdapter.getItem(position);

				// 行データを次画面に渡す
				Intent intent = new Intent(MainActivity.this,Main2Activity.class);
				intent.putExtra("DATA",webData);
				MainActivity.this.startActivityForResult(intent, 101);

				// 選択した行を保存
				MainActivity.this.position = position;

			}
		});


第二画面から戻って来た時の処理を追加

第二画面で変更された行データを使用して ListView を再表示する
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if ( requestCode == 101  ) {

			if ( resultCode == MainActivity.RESULT_OK ) {
				// ボタンの種類
				String result = data.getStringExtra("RESULT");
				if ( result.equals("終わったよ") ) {

				}
				if ( result.equals("更新したよ") ) {

					// 更新後データの取得
					WebData webData_update = (WebData) data.getSerializableExtra("DATA");

					WebData webData_listview = arrayAdapter.getItem(MainActivity.this.position);
					// 更新されたデータのセット
					webData_listview.name = webData_update.name;
					// 再表示
					listView.setAdapter(arrayAdapter);

				}
			}

		}

	}


第二画面に変数定義

private TextView link;
private TextView name;
private EditText editText;

第二画面の初期画面表示

以降、onCreate にて
		// 画面コントロールのインスタンス取得
		link = (TextView) Main2Activity.this.findViewById(R.id.textViewLink);
		name = (TextView) Main2Activity.this.findViewById(R.id.textViewName);
		editText = (EditText) Main2Activity.this.findViewById(R.id.editText);

		// データの取得
		Intent intent = Main2Activity.this.getIntent();
		WebData webData = (WebData) intent.getSerializableExtra("DATA");

		// データのセット
		link.setText(webData.link);
		name.setText(webData.name);
		editText.setText(webData.name);

ただ戻るだけのボタンの処理
		Button buttonReturn = (Button) Main2Activity.this.findViewById(R.id.buttonReturn);
		buttonReturn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				Intent intent = new Intent();
				intent.putExtra("RESULT", "終わったよ");
				setResult(Main2Activity.RESULT_OK, intent);

				// 第二画面終了
				Main2Activity.this.finish();

			}
		});


画面上の更新処理
		Button buttonUpdate = (Button) Main2Activity.this.findViewById(R.id.buttonUpdate);
		buttonUpdate.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				Intent intent = new Intent();
				intent.putExtra("RESULT", "更新したよ");

				Intent intentStart = Main2Activity.this.getIntent();
				WebData webData = (WebData) intentStart.getSerializableExtra("DATA");
				// 入力内容をセットする
				webData.name = editText.getText().toString();

				intent.putExtra("DATA", webData);
				setResult(Main2Activity.RESULT_OK, intent);

				// 第二画面終了
				Main2Activity.this.finish();

			}
		});






posted by at 2017-07-02 00:47 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2017年07月01日

Android Studio : LiveDoor のお天気情報をリストビューに表示する手順

手順1

AndroidManifest.xml に、以下を追加する

<uses-permission android:name="android.permission.INTERNET"/>

手順2

build.gradle(Module) に、OkhttpGoogle Gson の記述を追加する
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.squareup.okhttp3:okhttp:3.8.1'
    compile 'com.google.code.gson:gson:2.8.1'

}


activity_main.xml に ListView をセット
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>


JSON データをデシリアイズする為のクラスを作成
public class Weather {

	WebData[] pinpointLocations;

}
public class WebData {

	String link;
	String name;

	@Override
	public String toString() {
		return name;
	}
}

インターネットアクセス用のクラス

HttpAccess クラスを追加
import android.os.AsyncTask;

import java.io.IOException;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class HttpAccess {

	private OkHttpClient okHttpClient;
	private String url;

	public interface OnAsyncTaskListener {
		abstract public void onAsyncTaskListener(String s);
	}

	public HttpAccess(String url) {
		this.okHttpClient = new OkHttpClient();
		this.url = url;
	}

	public void sendGet(final OnAsyncTaskListener listener ) {

		new AsyncTask<Void,Void,String>(){
			@Override
			protected String doInBackground(Void... params) {
				String result = "[\"error\"]";

				Request.Builder builder = new Request.Builder();
				builder.url(HttpAccess.this.url);
				Request request = builder.build();

				Response response = null;
				try {
					response = HttpAccess.this.okHttpClient.newCall(request).execute();
					result = response.body().string();
				}
				catch (IOException e) {
					e.printStackTrace();
				}

				return result;
			}

			// UI スレッド処理
			@Override
			protected void onPostExecute(String s) {
				super.onPostExecute(s);

				listener.onAsyncTaskListener(s);

			}
		}.execute();

	}

}


private 変数を三つ作成
private ListView listView;
private ArrayAdapter<WebData> arrayAdapter;
private HttpAccess httpAccess;


ListView と ArrayAdapter のインスタンスを作成

以降 onCreate にて。
listView = (ListView) MainActivity.this.findViewById(R.id.listView);
arrayAdapter = new ArrayAdapter<WebData>(MainActivity.this,android.R.layout.simple_list_item_1);


ListView に ArrayAdapter をセット

listView.setAdapter(arrayAdapter);

API を呼び出して結果をリストビューにセット
new HttpAccess("http://weather.livedoor.com/forecast/webservice/json/v1?city=270000")
	.sendGet(new HttpAccess.OnAsyncTaskListener() {
		@Override
		public void onAsyncTaskListener(String s) {

			Gson gson = new Gson();
			Weather weather = gson.fromJson(s, Weather.class);

			arrayAdapter.clear();
			arrayAdapter.addAll(weather.pinpointLocations);

		}
	});


さらに Intent で第二画面

Android Studio : LiveDoor のお天気情報をリストビューに表示した後、第二画面で name を変更して第一画面で再表示する手順



タグ:android java
posted by at 2017-07-01 23:08 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2017年04月24日

Android の教科書到着しました。



ダウンロードページ

一部、実機でないとできないものもありますが、主に3年生向きとして考えています。

第1章 アプリを作るための準備

第2章 ツータッチ楽々メール――ラクにメールを送信しよう

本文では、内臓メールに intent で呼び出してるようですが、こちらで実際にメール送信します。
Android Studio で、javamail を gradle に書いて添付ファイル付きメール送信を行う

第3章 魅惑のあんばやしルーレット――お祭りでよく見るルーレットに挑戦!
(RecyclerView と CardView)

ListView 前提なので、先に簡単なリストビューを実装します。
Google スプレッドシートの内容を JSON として localhost で取得する手順

第4章 ○時になったよ!――カンタン便利なお知らせアラーム

通知。たぶんあまりおもしろく無い。

第5章 これ覚えておきたいねん――忘れると困ることは記録しよう!

フラグメントの一般論が書いてあるので、知る事は重要。ただ、実装としては Java の勉強の舞台として使用している Android としてあまり重要ではありません。

第6章 振って、ゆらして琉球音階――センサーとサウンドを活用しよう

ここは実機用

第7章 チキチキ障害物レース――センサーとSurfaceViewでゲームを作ろう!

ゲームは余程の事が無いかぎりしません。

第8章 パッと撮ってビャッ――写真はクラウドに残そう!

Dropbox のアカウントで API + カメラ。
Dropbox やるくらいなら、Firebase やります。

第9章 いつでもどこでも避難所マップ――地図&オープンデータの活用

Google MAP ですが、あまり役に立たないのでたぶん無視します。

第10章 ジョギングの友――ドロイド君と走ろう

SQLite ですが、Google MAP がらみなので微妙。
SQLite そのものは簡単ですが、環境やらAPIレベルやらの全体像把握がめんどくさい。

第11章 マインドストームEV3リモコン――Android端末でロボットを操作しよう

ここも実機用( Bluetooth )




posted by at 2017-04-24 11:13 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2017年04月14日

Android Studio をちょっと古い PC で使うと エミュレータが実行されなかった。



Android Studio 2.3.1 です。なんだか、インストール時に指定した sdk の場所が無視されてるみたいなんですが...

30台の PC が実は2種類だった

片方は、エミュレータが動いて、ちょっと古いほうが軒並みエミュレータが起動しないというトラブルに見舞われまして、今期授業最初の日はさんざんでした。メモリが 4G しかない PC に 64bit の Windows7 で Android Studio 2.3.1 のインストールを開始したわけですが、インストールファイルがでかいので、30台一度にダウンロードするわけにもいかず、一つのファイルを順番にネットワークでコピーしました。

それでも時間かかるので、途中からいくつかの USB 使ってコピーしました。今時の USB メモリって容量大きいんですね。

で、インストールも終わり( Android 6.0 で揃えたので さらに システムイメージのダウンロードも)、エミュレータを起動しようとすると、『動かない』。最初何故半数あまりの PC でトラブルなのか解らなかったんですが、PC 環境がそれほどいいものでも無いので、『え゛え゛え゛ 32ビットに戻すのか???』とか、怖ろしい未来が脳裏を横切りましたが、それらが共通のマザーボードだと解り、GPU の問題だと結論付けたんですが、それが解ったのは授業が終わってからで、作業は次の日へ持ち越し。

何故か、2台の PC がメモリを喰って動かない

30台同時に学生が30人でテストしてるので、なかなか原因を自分が前に座って調査するわけにも行かず(他の授業もあるし、MySQL のインストールもあるし)、結局なんとか全員のエミュレータ起動して、PC からクリップボードでエミュレータにコピーするところまでで終了。

で、授業終了後、確認してみたら・・・・

凶悪な量の Windows Update (230オーバー) が終了していなかったせいでした。放置してその日は終わり、それが木曜だったので、確認は月曜日。

まあ、なんとかなった。

来週は Eclipse で、WindowBuilder と Tomcat8 の開発環境整えます。

関連する記事

Pleiades All in One(NEON) で、Windows アプリを作成する手順( WindowBuilder + Swing デザイナー or SWT デザイナー[JFace] )





posted by at 2017-04-14 23:15 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2016年12月12日

Android Studio で、Failed to find target with hash string というエラーが出たら、Module の build.gradle を変更します

要するに作成した時は、実機の都合等で 6.0 をインストール済みの環境であったりして、そのプロジェクトを普段使っている実機では 4.4.4 とかの環境で実行しようとすると、当然プロジェクトに矛盾が生じるわけですが、たいていはバージョン関連の数値を自分が普段使っている数値に書き換えれば動作すると思います。

エラーが出た build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"
    defaultConfig {
        applicationId "jp.iseifu.kaisya"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.google.firebase:firebase-core:9.6.1'
    compile 'com.google.firebase:firebase-database:9.6.1'
    testCompile 'junit:junit:4.12'
    compile files('libs/tools.jar')
}

apply plugin: 'com.google.gms.google-services'


自分の環境の build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "23.0.3"
    defaultConfig {
        applicationId "jp.iseifu.kaisya"
        minSdkVersion 19
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:22.2.1'
    testCompile 'junit:junit:4.12'
    compile 'com.google.firebase:firebase-core:9.6.1'
    compile 'com.google.firebase:firebase-database:9.6.1'
    compile files('libs/tools.jar')
}

apply plugin: 'com.google.gms.google-services'

違いはバージョン関係の行が4行あり、インストールされている com.android.support:appcompat のバージョンでした。


posted by at 2016-12-12 15:11 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2016年07月25日

Android Studio で Fragment の tools:layout で画面を指定して MainActivity には処理を書かないアプリケーション

以下がボタンの画面定義ですが、<Fragment> で使用されます。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ボタン1"
        android:id="@+id/button"
        android:layout_weight="1"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ボタン2"
        android:id="@+id/button2"
        android:layout_weight="1"/>

</LinearLayout>
この定義は、二つのフラグメントで使用されます。
public class Buttons extends Fragment {

	@Nullable
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

		View view = inflater.inflate(R.layout.buttons, container, false);

		// **************************
		// 上段左ボタンの処理
		// **************************
		view.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				EditText et = (EditText) getActivity().findViewById(R.id.editText);
				et.setText("最初のフラグメントから、一つ目のボタンを使う");
			}
		});

		// **************************
		// 上段右ボタンの処理
		// **************************
		view.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// **************************
				// 別のフラグメントへのアクセス
				// **************************
				// フラグメントマネージャを取得して
				FragmentManager fm = getFragmentManager();
				// 目的のフラグメントを取得
				Fragment target = fm.findFragmentById(R.id.fragment2);
				if ( target != null ) {
					// その View を取得して
					View view = target.getView();
					// 中のコンテンツを取得する
					Button button = (Button) view.findViewById(R.id.button);
					// 下段の左ボタンのテキストを赤に
					button.setTextColor(Color.parseColor("#FF0000"));
				}

			}
		});

		return view;

	}

}


二つ目です
public class Buttons2 extends Fragment {

	@Nullable
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

		View view = inflater.inflate(R.layout.buttons, container, false);

		// **************************
		// 下段左ボタンの処理
		// **************************
		view.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				EditText et = (EditText) getActivity().findViewById(R.id.editText2);
				et.setText("二つ目のフラグメントから、一つ目のボタンを使う");
			}
		});

		// **************************
		// 下段右ボタンの処理
		// **************************
		view.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// **************************
				// 別のフラグメントへのアクセス
				// **************************
				// フラグメントマネージャを取得して
				FragmentManager fm = getFragmentManager();
				// 目的のフラグメントを取得
				Fragment target = fm.findFragmentById(R.id.fragment);
				if ( target != null ) {
					// その View を取得して
					View view = target.getView();
					// 中のコンテンツを取得する
					Button button = (Button) view.findViewById(R.id.button);
					// 上段の左ボタンのテキストを赤に
					button.setTextColor(Color.parseColor("#FF0000"));
				}

			}
		});

		return view;

	}
}


以下は、MainActivity で使用される画面です
<?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="lightbox.june.fragmenttest.MainActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/scrollView">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <fragment
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:name="lightbox.june.fragmenttest.Buttons"
                android:id="@+id/fragment"
                tools:layout="@layout/buttons"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/editText"/>

            <fragment
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:name="lightbox.june.fragmenttest.Buttons2"
                android:id="@+id/fragment2"
                tools:layout="@layout/buttons"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/editText2"/>

        </LinearLayout>
    </ScrollView>

</RelativeLayout>

ボタンの各処理は、フラグメントで処理され、activity_main のコンテンツは getActivity().findViewById で取得します。フラグメントから、他のフラグメントのアクセスは、

1) getFragmentManager()
2) findFragmentById()
3) getView()
4) findViewById()

と、順に取得します



posted by at 2016-07-25 20:28 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2016年07月14日

Android の SeekBar を縦方向で使用する設定



XML の画面定義部分の変更だけで対応できました。(setOnSeekBarChangeListener でイベント実装してテスト)
デザイン画面では縦にならず、そもそも、Android Studio のプロパティ一覧に無い android:rotation が必要です。

また、位置調整は、回転した後の位置関係で行います。layout_marginLeft がマイナスなのは、何もしないと右にかなり移動した位置になるからです。
<?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.lightbox.seekbartest.MainActivity">

    <SeekBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/seekBar"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:rotation="270"
        android:minWidth="100dp"
        android:layout_marginTop="50dp"
        android:layout_marginLeft="-50dp" />
</RelativeLayout>



posted by at 2016-07-14 11:23 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

2016年06月27日

Android 5.1(API 22) と Android 4.4(API 19) でのそれぞれの DatePicker ダイアログの扱い

Android 5.1(API 22) で DatePicker ダイアログを使用するには、テーマにスタイルを設定する必要があります。何もしないで呼び出すと、大きなカレンダーが表示されて変更できません。DatePickerDialog のコンストラクタで定義したスタイル指定する方法もありますが、テーマに全て設定するほうが簡単です。
<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:datePickerStyle">@style/MyDatePicker</item>
        <!-- ダイアログ用 -->
        <item name="android:dialogTheme">@style/MyDialogTheme</item>
    </style>

    <!-- コントロール用 -->
    <style name="MyDatePicker" parent="android:Widget.Material.DatePicker">
        <item name="android:datePickerMode">spinner</item>
    </style>
    <!-- ダイアログ用 -->
    <style name="MyDialogTheme" parent="android:Theme.Material.Light.Dialog">
        <item name="android:datePickerStyle">@style/MyDatePicker</item>
    </style>

</resources>


しかし、この追加されたスタイルは、コントロールもダイアログも Android 4.4(API 19) では使用できないので Android 4.4(API 19) でテストする時はコメントにする必要があります。

実行処理
package lightbox.june.datepickercontrol;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.DatePicker;

import java.util.Calendar;

public class MainActivity extends AppCompatActivity {

	private Calendar calendar;
	private int year;
	private int monthOfYear;
	private int dayOfMonth;
	private DatePicker dp;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		dp = (DatePicker) MainActivity.this.findViewById(R.id.datePicker);

		// ********************************
		// 今日の日付
		// ********************************
		calendar = Calendar.getInstance();
		year = calendar.get(Calendar.YEAR);
		monthOfYear = calendar.get(Calendar.MONTH);
		dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);

		// ******************************
		// ボタン1
		// Spinner
		// ******************************
		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// ********************************
				// Spinner DatePicker ダイアログの処理
				// ********************************
				DatePickerDialog spinnerDatePicker;
				spinnerDatePicker = new DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() {
					@Override
					public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
						Log.i("lightbox", String.format("%d-%d-%d",year,(monthOfYear+1),dayOfMonth ) );
					}
				}, year, monthOfYear, dayOfMonth);
				// 表示前に日付を設定する時の日付の変更方法
				spinnerDatePicker.getDatePicker().updateDate(year, monthOfYear, dayOfMonth);
				spinnerDatePicker.show();

				// ********************************
				// Spinner DatePicker コントロールの処理
				// ********************************
				dp.setSpinnersShown(true);
				dp.setCalendarViewShown(false);
				Log.i("lightbox", String.format("%d/%d/%d", dp.getYear(),(dp.getMonth()+1),dp.getDayOfMonth() ) );

			}
		});

		// ******************************
		// ボタン2
		// CalendarView
		// ******************************
		MainActivity.this.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// ********************************
				// CalendarView DatePicker ダイアログの処理
				// ********************************
				DatePickerDialog CalendarView;
				CalendarView = new DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() {
					@Override
					public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
						Log.i("lightbox", String.format("%d-%d-%d",year,(monthOfYear+1),dayOfMonth ) );
					}
				}, year, monthOfYear, dayOfMonth);		// 表示前に日付を設定
				// 表示前に日付を設定する時の日付の変更方法
				CalendarView.getDatePicker().updateDate(year, monthOfYear, dayOfMonth);
				// 表示方法の変更
				CalendarView.getDatePicker().setSpinnersShown(false);
				CalendarView.getDatePicker().setCalendarViewShown(true);
				CalendarView.show();

				// ********************************
				// CalendarView DatePicker コントロールの処理
				// ********************************
				dp.setSpinnersShown(false);
				dp.setCalendarViewShown(true);

				Log.i("lightbox", String.format("%d/%d/%d", dp.getYear(),(dp.getMonth()+1),dp.getDayOfMonth() ) );
			}
		});

		// ******************************
		// ボタン3
		// Spinner DialogFragment
		// Spinner + CalendarView
		// ******************************
		MainActivity.this.findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// ********************************
				// ダイアログ・フラグメント
				// ********************************
				DialogFragment newFragment = new DatePickerFragment();
				newFragment.show(getSupportFragmentManager(), "datePicker");

				// ********************************
				// Spinner + CalendarView
				// DatePicker コントロールの処理
				// ********************************
				DatePicker dp = (DatePicker) MainActivity.this.findViewById(R.id.datePicker);
				dp.setSpinnersShown(true);
				dp.setCalendarViewShown(true);
				Log.i("lightbox", String.format("%d/%d/%d", dp.getYear(),(dp.getMonth()+1),dp.getDayOfMonth() ) );
			}
		});

	}

	// ******************************
	// DialogFragment
	// ******************************
	public static class DatePickerFragment extends DialogFragment
		implements DatePickerDialog.OnDateSetListener {

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {

			// 初期値を DatePicker コントロールより取得
			DatePicker dp = (DatePicker) DatePickerFragment.this.getActivity().findViewById(R.id.datePicker);
			int year = dp.getYear();
			int month = dp.getMonth();
			int day = dp.getDayOfMonth();

			return new DatePickerDialog(getActivity(), this, year, month, day);
		}

		public void onDateSet(DatePicker view, int year, int month, int day) {
			Log.i("lightbox", String.format("%d-%d-%d",year,(month+1),day ) );
		}
	}
}


3つ目のボタンでは、DialogFragment を使用しており、初期値として DatePicker コントロールの値を使用しています。

Android Deveroper : DialogFragment for a date picker


※ 全てのソースコード



posted by at 2016-06-27 13:07 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする

Android 5.1(API 22) と Android 4.4(API 19) でのそれぞれの DatePicker コントロールの扱い

手持ちの Android が 5.1 なら何も考えなくて良いのですが、実機テストをする為に Android 4.4 を Min SDK に設定しています。



この状態で、DatePicker コントロールを貼り付けると以下のようになります。



そして、プレビューを API 19 に変更すると以下のようになります。



実際、実機で実行するとその通りに Spinner 状態で表示され、setSpinnersShown と setCalendarViewShown で変更すると、表示も変わってくれます。

    

しかし、Android5.1(API 22)では、setSpinnersShown と setCalendarViewShown は動作してくれません。初期表示はカレンダー状態になります。( 月の変更の方法が良くわかりません )



そして、setSpinnersShown と setCalendarViewShown を動作させるには、スタイルを定義して DatePicker コントロール に設定してやる必要があります。ただ、これをする場合 Android 4.4(API 19) では、動作しないので Min SDK を変更する必要が出てきてしまいます。( 当然ですが、デバイス選択で実機が Gray out するので実機には転送できなくなります )


<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>

    </style>

    <style name="MyDatePicker" parent="android:Widget.Material.DatePicker">
        <item name="android:datePickerMode">spinner</item>
    </style>

</resources>






メインテーマに以下のように設定しておけば、DatePicker コントロールにスタイルを設定する必要はありません
<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:datePickerStyle">@style/MyDatePicker</item>
    </style>

    <style name="MyDatePicker" parent="android:Widget.Material.DatePicker">
        <item name="android:datePickerMode">spinner</item>
    </style>

</resources>




タグ:android
posted by at 2016-06-27 10:31 | Comment(0) | Android | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します


Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX