SQLの窓

2015年10月26日


Android の Data Binding における include を使用した画面分割

Android デベロッパーの Data Binding Guide に書かれていますが、bind:user="@{user}" のように variable で指定した変数を引き継ぐだけです。



この記述は、引き継がれた( include された) 画面にも記述して、さらに第三画面を include できます。



注意 : デザイン画面でエラーのようなものが出る場合は、( とりあえず Clean Project を実行して ) 左上の x をクリックして閉じて下さい。( カスタム要素のせいです )


画面全体のソースコード

引き継がれた( include された) 画面
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:bind="http://schemas.android.com/apk/res-auto"
        tools:context=".MainActivity">

    <data>
        <variable
            name="user"
            type="sample.lightbox.androidbind1017.Syain"/>
    </data>

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.syozoku}"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:id="@+id/textView3"
            android:layout_margin="4dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.sname}"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:id="@+id/textView4"
            android:layout_margin="4dp"/>

        <NumberPicker
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/numberPicker"/>

        <Spinner
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/spinner"
            android:spinnerMode="dropdown"/>

        <DatePicker
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/datePicker"
            android:datePickerMode="spinner"/>

        <include
            layout="@layout/ex_contents2"
            android:id="@+id/ex2"
            bind:user="@{user}"/>

    </LinearLayout>
</layout>


第三画面
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:bind="http://schemas.android.com/apk/res-auto"
        tools:context=".MainActivity">

    <data>
        <variable
            name="user"
            type="sample.lightbox.androidbind1017.Syain"/>
    </data>

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


        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.kj}"
            android:id="@+id/editText2"
            android:background="@drawable/border"
            android:padding="5dp"/>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="TOP"
            android:id="@+id/button4"/>

    </LinearLayout>
</layout>

Data Binding 画面の注意事項

画面定義内は常に英数字・記号を使用する必要があります

現時点では、画面内の文字列に日本語を使用できません。実際使う場合は、初期値を直接書き込む場合とバインド用の変数に使う場合ですが、前者はリソースとして定義して日本語を使わずに参照擦れば動作します。しかし、後者では使え無い場合があります(使える場合もある)。


posted by lightbox at 2015-10-26 10:10 | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年10月01日


Android : DatePickerDialog で、4種類のダイアログを使い分ける( spinner と calendar の組み合わせ )

Android 5.1 ですが、プログラムからスタイルの 1属性を(容易には)変更できないようなので、二つのスタイルを用意して必要な DatePickerDialog を作成して使用します。何もしないと、大きなカレンダーになり、初期表示の日付の前後の日付選択は簡単ですが、年月の変更をしたい場合は、スピナーを組み合わせる必要があります。

しかし、スピナーへの変更がスタイル経由でしかできないので、DatePickerDialog のコンストラクタでテーマを指定できるほうを使って適宜選択します。





<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light">
    </style>

    <style name="MyDialogTheme" parent="android:Theme.Material.Light.Dialog">
        <item name="android:datePickerStyle">@style/MyDatePicker</item>
    </style>
    <style name="MyDialogTheme2" parent="android:Theme.Material.Light.Dialog">
        <item name="android:datePickerStyle">@style/MyDatePicker2</item>
    </style>

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


MainActivity
package sample.lightbox.calendar;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.DatePicker;

import java.util.Calendar;

public class MainActivity extends Activity {

	private DatePickerDialog spinnerDatePicker = null;
	private DatePickerDialog calendarDatePicker = null;

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

		final Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		int monthOfYear = calendar.get(Calendar.MONTH);
		int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);

		spinnerDatePicker = new DatePickerDialog(
				MainActivity.this,
				R.style.MyDialogTheme,
				new DatePickerDialog.OnDateSetListener() {
					@Override
					public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
						String buffer = String.format("%4d/%02d/%02d",year,monthOfYear+1,dayOfMonth);
						Log.i("lightbox",buffer);
					}
				},year,monthOfYear,dayOfMonth);

		calendarDatePicker = new DatePickerDialog(
				MainActivity.this,
				R.style.MyDialogTheme2,
				new DatePickerDialog.OnDateSetListener() {
					@Override
					public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
						String buffer = String.format("%4d/%02d/%02d",year,monthOfYear+1,dayOfMonth);
						Log.i("lightbox",buffer);
					}
				},year,monthOfYear,dayOfMonth);


		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				spinnerDatePicker.getDatePicker().setSpinnersShown(true);
				spinnerDatePicker.getDatePicker().setCalendarViewShown(false);
				spinnerDatePicker.show();
			}
		});

		MainActivity.this.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				spinnerDatePicker.getDatePicker().setSpinnersShown(false);
				spinnerDatePicker.getDatePicker().setCalendarViewShown(true);
				spinnerDatePicker.show();
			}
		});

		MainActivity.this.findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				spinnerDatePicker.getDatePicker().setSpinnersShown(true);
				spinnerDatePicker.getDatePicker().setCalendarViewShown(true);
				spinnerDatePicker.show();
			}
		});

		MainActivity.this.findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				calendarDatePicker.show();
			}
		});
	}

}

フラグメントバージョンは、Android Developer の Creating a Date Picker を参考にしますが、現状では getSupportFragmentManager では無く getFragmentManager を使用します。

また、常に spinner 側を使用するのであれば、メインテーマの中に、以下を入れてしまえばいいはずです。
<item name="android:dialogTheme">@style/MyDialogTheme</item>
参考


posted by lightbox at 2015-10-01 03:04 | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年09月13日


ViewSwitcher : 複数の画面または階層となる画面は、別 XML で定義して addView すると、Android Studio の Design で全ての画面をプレビューできます

activity_main.xml


image_1.xml


ViewSwitcher は、二つの View を切り替える事のできる ViewGroup ですが、ViewSwitcher の中で表示する二つの View をひとつづつ XML で定義して ViewSwitcher の addView で実際の画面を追加します。

主な特記事項

フリックによる画面切り替えを行う為、Detecting Common Gestures で解説されている GestureDetector を使用しています。また、イベントは GestureDetector.SimpleOnGestureListener を使用してイベントの記述を簡潔にしています。

onFling で、event2.getX() - event1.getX() によって左右どちらほフリックしたかを確認しており、絶対値で移動距離を確認できます。

ViewSwitcher の画面が変わる時のアニメーションは、setInAnimation と setOutAnimation で Android で定義されているフェードイン・フェードアウトを使用しています

通常、初期画面は setContentView(R.layout.activity_main); で作成されますが、ここでは画面の意味を明確にする為に、LayoutInflater で全ての画面( View ) のインスタンスを作成しています

MainActivity
package sample.lightbox.viewswitch;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ViewSwitcher;

public class MainActivity extends Activity  {

	private ViewSwitcher vs = null;

	// https://developer.android.com/training/gestures/detector.html
	private GestureDetector mDetector;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// 画面インスタンス作成用のオブジェクトをシステムから取得
		LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

		// メイン画面定義のインスタンスを作成して表示する
		// http://y-anz-m.blogspot.jp/2012/04/android-viewgroup.html
		RelativeLayout root = (RelativeLayout) inflater.inflate(R.layout.activity_main, null);
		setContentView(root);
//		setContentView(R.layout.activity_main);

		// 戻るボタンの処理
		findViewById(R.id.button_p).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				vs.showPrevious();
			}
		});
		// 進むボタンの処理
		findViewById(R.id.button_n).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				vs.showNext();
			}
		});

		// レイアウト用の XML より View のインスタンスを作成
		// ( inflate( id, null ) では、ルートのクラスのインスタンスとなる  )
		LinearLayout image1 = (LinearLayout) inflater.inflate(R.layout.image_1, null);
		LinearLayout image2 = (LinearLayout) inflater.inflate(R.layout.image_2, null);

		// ViewSwitcher に 作成した View を追加する
		vs = (ViewSwitcher) root.findViewById(R.id.viewSwitcher);
		vs.addView(image1);
		vs.addView(image2);
		// アニメーションの設定
		vs.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_in));
		vs.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));

		mDetector = new GestureDetector(MainActivity.this, new MyGestureListener());

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// この処理で、タッチイベントからジェスチャーが処理できるようになる
		mDetector.onTouchEvent(event);
		return super.onTouchEvent(event);
	}

	// フリックによる画面切り替えの為の定義
	class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
		private static final String DEBUG_TAG = "Gestures";

		@Override
		public boolean onDown(MotionEvent event) {
			Log.i(DEBUG_TAG, "onDown: " + event.toString());
			return true;
		}

		@Override
		public boolean onFling(MotionEvent event1, MotionEvent event2,
							   float velocityX, float velocityY) {
			vs.showNext();
			Log.i("DEBUG_TAG", (event2.getX() - event1.getX() )+"" );
			return true;
		}
	}
}


activity_main.xml
<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:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/buttons">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="戻る"
            android:id="@+id/button_p"
            android:layout_weight="1"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="進む"
            android:id="@+id/button_n"
            android:layout_weight="1"/>
    </LinearLayout>

    <ViewSwitcher
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewSwitcher"
        android:layout_below="@+id/buttons"/>
</RelativeLayout>


image_1.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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@drawable/kirin"/>
</LinearLayout>
image_2.xml は image_1.xml をコピーして画像を変更しています

参考ページ

Detecting Common Gestures

Android カスタム ViewGroup 用XMLのルートタグを merge にする



posted by lightbox at 2015-09-13 00:27 | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年09月06日


ViewFlipper(複数ビュー) と ViewSwitcher(2つまでのビュー)


ViewFlipper
(a:ViewSwitcher)
(b:ViewSwitcher)


基本的にどちらも同じですが、オプションとしての画面は ViewSwitcher で十分なのでこのような構成が現実的だと思います。

主な特記事項

ViewFlipper の 移動イベントは、どちらも MainActivity に implements View.OnClickListener する事によって、MainActivity 内のイベントとして処理しています。ボタンが複数ありますが、一つのイベントとして処理されるので、アニメーションの設定を両方に同じものを設定して簡潔になっています。

フェードインとフェードアウトのイベントは、Android に定義されているものと、ユーザ定義のものを両方使っています。どちらも定義上は大差無いのでほぼ同じ効果になります。ただ、ヨーザ定義は変更する事によって自由にアニメーションをカスタマイズできます。

メインの移動処理では、スライドインとスライドアウトを使用していますが、Android が定義しているのは片方向のみです。showPrevious に合わせた逆スライドは(必要であれば)ユーザ定義する必要があります。
package sample.lightbox.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.ViewFlipper;
import android.widget.ViewSwitcher;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class MainActivity extends Activity implements View.OnClickListener {

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

		// MainActivity 内でリスナーを作成( implements View.OnClickListener )
		MainActivity.this.findViewById(R.id.mainPrevious).setOnClickListener(this);
		MainActivity.this.findViewById(R.id.mainNext).setOnClickListener(this);

		// ViewSwitcher 内のボタン( 最初の View )
		MainActivity.this.findViewById(R.id.switcherButton1).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				ViewSwitcher vs = (ViewSwitcher) MainActivity.this.findViewById(R.id.viewSwitcher);
				// Android の アニメーションを使用
				vs.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_in));
				vs.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));
				vs.showNext();
			}
		});
		// ViewSwitcher 内のボタン( 次の View )
		MainActivity.this.findViewById(R.id.switcherButton2).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				ViewSwitcher vs = (ViewSwitcher) MainActivity.this.findViewById(R.id.viewSwitcher);
				// ユーザ作成 の アニメーションを使用
				vs.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.in_effect));
				vs.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.out_effect));
				vs.showPrevious();
			}
		});

	}

	@Override
	public void onClick(View v) {

		// アニメーション設定
		ViewFlipper vf = (ViewFlipper) MainActivity.this.findViewById(R.id.viewFlipper);
		// Android の アニメーションを使用
		vf.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left));
		vf.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_out_right));

		// 使用されたボタンの id を取得
		int id = v.getId();

		if (id == R.id.mainPrevious) {
			vf.showPrevious();
		}
		if (id == R.id.mainNext) {
			vf.showNext();
		}

	}

}


画面定義
<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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/buttons"
        android:focusableInTouchMode="true">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="前へ移動"
            android:id="@+id/mainPrevious"
            android:layout_weight="1"
            android:layout_marginLeft="10dp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="次へ移動"
            android:id="@+id/mainNext"
            android:layout_weight="1"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="10dp" />
    </LinearLayout>

    <ViewFlipper
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewFlipper"
        android:layout_below="@+id/buttons" >

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

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imageView"
                android:src="@drawable/animal_mark_kirin" />
        </LinearLayout>

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

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imageView2"
                android:src="@drawable/microphone1_boy" />
        </LinearLayout>

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

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imageView3"
                android:src="@drawable/present_usagi" />
        </LinearLayout>

        <ViewSwitcher
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/viewSwitcher" >

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

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="ViewSwitcher内ボタン"
                    android:id="@+id/switcherButton1" />
            </LinearLayout>

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

                <Button
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="ViewSwitcher内ボタン"
                    android:id="@+id/switcherButton2" />

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/imageView4"
                    android:src="@drawable/skea1" />
            </LinearLayout>
        </ViewSwitcher>

    </ViewFlipper>
</RelativeLayout>


in_effect.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="0"
    android:toAlpha="1.0"
    />

out_effect.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="1.0"
    android:toAlpha="0"
    />



posted by lightbox at 2015-09-06 00:17 | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年09月05日


ListView を使った AlertDialog で SD カード内のファイルのパスを取得する



以前から思っていたのですが、変数に日本語を使うと内容を説明しやすいので主な変数を全て日本語にして、かつ、クラス変数で参照が容易になるようにした上で、メソッドの処理を引数を使うのでは無く、この変数で処理を明示するようにしてみました。

主な特記事項

SD カードにアクセスする為に、AndroidManifest.xml には android.permission.READ_EXTERNAL_STORAGE または、android.permission.WRITE_EXTERNAL_STORAGE を uses-permission に設定する必要があります。

Environment.getExternalStorageState() で、SD カードが使用可能かどうかをチェックしています

この場合のダイアログは、ダイアログ内をクリックする毎に表示する内容や処理が変わります。固定部分は、Activity の onCreate で定義していますが、その他の部分は loadFileDialog(ユーザー作成のメソッド) 内で毎回設定してから、show メソッドで表示を行います。

ダイアログは、フラグメント(DialogFragment)では無いのでデバイスが回転するとリセットされます
package sample.lightbox.filedialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.File;

public class MainActivity extends Activity {

	private String tag = null;
	private File SDカードディレクトリ = null;
	private File 現在のファイルオブジェクト = null;
	private String 現在のパス文字列 = null;
	private String[] フォルダとファイルの一覧 = null;
	private AlertDialog.Builder ファイルダイアログ = null;

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

		// リソースよりデータを取得する
		tag = getResources().getString(R.string.app_name);

		// SDカードのパスを取得( Environment クラス )
		String 外部ストレージの状態 = Environment.getExternalStorageState();
		if (外部ストレージの状態.equals(Environment.MEDIA_MOUNTED)) {
			SDカードディレクトリ = Environment.getExternalStorageDirectory();
			現在のパス文字列 = SDカードディレクトリ.getAbsolutePath();
			Log.i(tag, 現在のパス文字列);
		}

		// ファイルダイアログの固定部分の定義
		ファイルダイアログ = new AlertDialog.Builder(MainActivity.this);
		ファイルダイアログ
				.setPositiveButton("キャンセル", null)
				.setNegativeButton("親フォルダ", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						if (現在のパス文字列.equals(SDカードディレクトリ.getAbsolutePath())) {
							// SDカードより上には移動しない
							return;
						}

						現在のファイルオブジェクト = 現在のファイルオブジェクト.getParentFile();
						現在のパス文字列 = 現在のファイルオブジェクト.getAbsolutePath();
						フォルダとファイルの一覧 = 現在のファイルオブジェクト.list();
						loadFileDialog();

					}
				});


		// ボタン(SDカード参照) のイベント
		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// ボタンクリックで表示する場合は、常に SDカードディレクトリから
				現在のファイルオブジェクト = SDカードディレクトリ;
				現在のパス文字列 = 現在のファイルオブジェクト.getAbsolutePath();
				フォルダとファイルの一覧 = 現在のファイルオブジェクト.list();
				loadFileDialog();

			}
		});
	}

	// ファイルダイアログの表示
	void loadFileDialog() {

		// ダイアログの作成と振る舞いの定義
		// ※ 注意 : フラグメントでは無いのでデバイスが回転するとリセットされます
		ファイルダイアログ
				.setTitle(現在のパス文字列)
				.setItems(フォルダとファイルの一覧, new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// 選択したファイルのパスの作成
						StringBuffer 選択したファイルのパス = new StringBuffer(現在のパス文字列);
						選択したファイルのパス
								.append(File.separator)
								.append(フォルダとファイルの一覧[which]);
						File ワークファイルオブジェクト = new File(選択したファイルのパス.toString());

						if (ワークファイルオブジェクト.isFile()) {
							// ファイル名のみ の表示
							Toast.makeText(MainActivity.this, フォルダとファイルの一覧[which], Toast.LENGTH_SHORT).show();
						} else {
							現在のファイルオブジェクト = ワークファイルオブジェクト;
							現在のパス文字列 = 現在のファイルオブジェクト.getAbsolutePath();
							フォルダとファイルの一覧 = 現在のファイルオブジェクト.list();
							loadFileDialog();
						}
					}
				});

		ファイルダイアログ.show();
	}

}


画面定義
<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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="SDカード参照"
        android:id="@+id/button"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>



posted by lightbox at 2015-09-05 20:56 | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2015年07月09日


Tools クラスの Activity を必要とする static メソッドをインスタンスメソッドに書き換えた AndroidTools クラス

tools.jar に追加しました

tools.jar

(Tools/Tools2/TestArrayAdapter/AndroidTools)

当たり前ですが、インスタンスにすると static メソッドに渡していた Activity をインスタンス内で保持できるので、引数が一つ減る事になります。しかし、これで各処理に Activity が密接に結びついている事が解ってかつ static と インスタンスの違いも明確になる『初心者訓練用』の色が明確になったテストライブラリセットとなりました。

AndroidTools.java
package jp.android.work;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;

/**
 * Created by lightbox on 2015/07/06.
 */
public class AndroidTools {
	private Activity context = null;

	public AndroidTools(Activity context) {
		this.context = context;
	}

	// 確認 メッセージボックス( メッセージのみ )
	public void messageBox(String message, final Tools.OnMessageBoxListener listener) {

		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
		alertDialogBuilder.setTitle("確認");
		alertDialogBuilder.setMessage(message);

		alertDialogBuilder.setPositiveButton("OK",
			new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					if (listener != null) {
						listener.onMessageBoxYesListener();
					}
				}
			});

		alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
			@Override
			public void onCancel(DialogInterface dialog) {
				if (listener != null) {
					listener.onMessageBoxNoListener();
				}
			}
		});

		alertDialogBuilder.setCancelable(true);
		// アラートダイアログを作成します
		AlertDialog alertDialog = alertDialogBuilder.create();
		alertDialog.show();

	}

	// YES or NO メッセージボックス( タイトルとメッセージ両方指定)
	public void messageBox(String title, String message, final Tools.OnMessageBoxListener listener) {

		// ダイアログ作成用オブジェクト作成
		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
		alertDialogBuilder.setTitle(title);
		alertDialogBuilder.setMessage(message);

		// YES ボタン作成
		alertDialogBuilder.setPositiveButton("YES",
			new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					if (listener != null) {
						listener.onMessageBoxYesListener();
					}
				}
			});

		// NO ボタン作成
		alertDialogBuilder.setNegativeButton("NO",
			new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					if (listener != null) {
						listener.onMessageBoxNoListener();
					}
				}
			});

		alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
			@Override
			public void onCancel(DialogInterface dialog) {
				if (listener != null) {
					listener.onMessageBoxNoListener();
				}
			}
		});

		alertDialogBuilder.setCancelable(true);
		// アラートダイアログを作成します
		AlertDialog alertDialog = alertDialogBuilder.create();
		alertDialog.show();
	}

	public void callBrowser(String url) {
		// ブラウザの呼び出し
		Uri uri = Uri.parse(url);
		Intent intent = new Intent(Intent.ACTION_VIEW, uri);
		if (intent.resolveActivity(context.getPackageManager()) != null) {
			context.startActivity(intent);
			return;
		}

		// 対応するアプリが無い
		Tools.longToast(
			context,
			"ブラウザを呼び出せません"
		);
		return;

	}

	// 短いトースト
	public void shortToast(String message) {
		Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
	}
	// 長いトースト
	public void longToast(String message) {
		Toast.makeText(context, message, Toast.LENGTH_LONG).show();
	}

	// 単純なアクティビテイの呼び出し
	public void callActivity( Class<?> cls, int requestCode) {
		// Activity呼び出し
		Intent intent = new Intent(context, cls);
		context.startActivityForResult(intent, requestCode);

	}

	// オブジェクトを引き渡しての呼び出し
	public void callActivity( Class<?> cls, int requestCode, String name, Serializable data) {
		// Activity呼び出し
		Intent intent = new Intent(context, cls);
		intent.putExtra(name,data);
		context.startActivityForResult(intent, requestCode);
	}

	// OK で終了
	public void okFinish(Intent intent) {
		context.setResult(context.RESULT_OK, intent);
		context.finish();
	}
	// CANCELED で終了
	public void cancelFinish(Intent intent) {
		context.setResult(context.RESULT_CANCELED, intent);
		context.finish();
	}


	// Private な アプリデータの保存
	public void putPreferences(String target, String key, String data) {
		SharedPreferences sp = context.getSharedPreferences(target, context.MODE_PRIVATE);
		SharedPreferences.Editor editor = sp.edit();
		editor.putString(key, data);
		editor.commit();

	}

	// Private な アプリデータの読み込み
	public String getPreferences( String target, String key) {
		SharedPreferences sp = context.getSharedPreferences(target, context.MODE_PRIVATE);
		return sp.getString(key, "_nodata");

	}

	// 汎用型コントロール参照
	public <T> T useView(int id) {
		T view = null;
		view = (T) context.findViewById(id);
		return view;
	}

	// ボタン用コントロール参照( イベント引数付き )
	public Button useButton(int id, View.OnClickListener listener) {
		Button button = (Button) context.findViewById(id);
		if (listener != null) {
			button.setOnClickListener(listener);
		}
		return button;
	}

	// ボタン用コントロール参照( イベントなし )
	public Button useButton(int id) {
		Button button = (Button) context.findViewById(id);
		return button;
	}

	// テキストファイル( プライベート書き込み )
	public void saveText(String name, String text) throws Exception {

		FileOutputStream outStream = context.openFileOutput(name, android.content.Context.MODE_PRIVATE);
		OutputStreamWriter writer = new OutputStreamWriter(outStream);
		writer.write(text);
		writer.flush();
		writer.close();

	}

	// テキストファイル( 読み込み )
	public String loadText(String name) throws Exception {

		FileInputStream fis = context.openFileInput(name);
		int size = fis.available();
		InputStreamReader isr = new InputStreamReader(fis);
		BufferedReader br = new BufferedReader(isr);
		StringBuffer all_string = new StringBuffer(size);
		String str = null;
		while ((str = br.readLine()) != null) {
			// 初回以外は前に改行を挿入する
			if (!all_string.toString().equals("")) {
				all_string.append("\n");
			}
			all_string.append(str);
		}
		br.close();

		return all_string.toString();

	}
}


関連する記事



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

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

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

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

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


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

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

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

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

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



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり