SQLの窓

2016年05月28日


ブックマークレット IFRAME ユニット作成ツール

https では無いページ用です。実行したページに IFRAME のウインドウを埋め込むコードのセットを作成するツールです。URL には、js ファイルの URL を入力し、さらに IFRAME のサイズを入力して実行します。

一つ目の TEXTAREA には、ブクマークレットを登録する為のリンクの HTML コードが作成され、二つ目の TEXTAREA には、.js の中に書き込む基本コードが作成されます。( .js は UTF-8 で保存します )

js URL
IFRAME 幅 IFRAME 高さ


WEB サイトをお持ちで無い方は、Google ドライブを使用できます。

Google ドライブにWEBページを作成する方法

▼ サンプル
https://b3612ccaef41231d7e34cda5ea0b9ed5af2eb17d.googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE/bml.js



posted by lightbox at 2016-05-28 00:33 | ブックマークレットコード | このブログの読者になる | 更新情報をチェックする

2016年05月27日


Google Chrome で音声認識の結果をブログの投稿テキストエリアに転送するブックマークレット



この Seesaa ブログでもテストしました(リッチテキストは使用できません)。ブックマークレットを実行すると、ページの左上に IFRAME のウインドウを埋め込みます。その後、ページ内の対象のテキストエリアにカーソルを置くと開始ボタンが使えるようになるので『開始』をクリックします。

あとは、マイクで話すだけです。時々固まって動作しなくなる場合があるのでその場合は、『終了ボタン』を押すして再度開始ボタンを押して再開して下さい。

終了ボタンを押すと停止状態になり、テキストエリア内のテキストを編集しても結構です。最後に改行等を入れて開始ボタンで再開すると、最後の位置に追加して行きます。

長い時間何も音声入力が無いと自動的に終了します。

Google Chrome で音声認識の精度は想像以上に凄いです。学生がおもしろがって般若心経を朗読はじめたんですが、見事に認識されました(凄い)。

※ 前後にある文章や語句によって結果を変更して行くのがリアルタイムに見て取れる場合があります
▼ ブックマークレット登録用リンク
音声からテキスト

コードのメインは、Google Chrome での音声認識処理 を使用しています。但し、処理部分は私のサイトの recognition.js の中にあります。
parent.document.getElementById("if").style.position='absolute';
parent.document.getElementById("if").style.width='400px';
parent.document.getElementById("if").style.height='100px';
parent.document.getElementById("if").style.left='0px';
parent.document.getElementById("if").style.top='0px';
parent.document.getElementById("if").style.zIndex=0x7FFFFFFF;
parent.document.getElementById("if").style.borderColor='#000000';
parent.document.getElementById("if").style.borderWidth='1px';
parent.document.getElementById("if").style.borderStyle='solid';

parent.window.ds = parent.document.createElement('div');
parent.window.ds.setAttribute('id','ds')
parent.document.body.appendChild(parent.window.ds);
parent.document.getElementById("ds").style.position='absolute';
parent.document.getElementById("ds").style.width='400px';
parent.document.getElementById("ds").style.height='100px';
parent.document.getElementById("ds").style.left='8px';
parent.document.getElementById("ds").style.top='8px';
parent.document.getElementById("ds").style.zIndex=0x7FFFFFFE;
parent.document.getElementById("ds").style.backgroundColor='#000000';

var userAgent = window.navigator.userAgent.toLowerCase();

if (userAgent.indexOf("msie") > -1) {
	parent.document.getElementById("ds").style.filter='alpha(opacity=18)';
}
else {
	parent.document.getElementById("ds").style.opacity=.18;
}


str="";
str+="<body style='margin:0;background-color:#ffffff;padding:15px;'> \n";
str+="<style> \n";
str+=" * { \n";
str+=" font-family:";
str+=" \"メイリオ\", Meiryo, \"MS Pゴシック\"; \n";
str+=" font-size:12px;";
str+="} \n";
str+="</style> \n";

str+="<"+"script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js\"></"+"script> \n";
str+="<div id=\"check\"></div> \n";
str+="<input id=\"st_btn\" type=\"button\" value=\"開始\" disabled> \n";
str+="<input id=\"ed_btn\" type=\"button\" value=\"終了\" disabled> \n";
str+="<div id=\"info\" style='display:inline-block;'></div> \n";
str+="<div id=\"result\"><div id=\"first_text\"></div></div> \n";

str+="<"+"script> \n";
str+="$( function(){ \n";
str+=" \n";
str+="	load_action(); \n";
str+=" \n";
str+="} ); \n";
str+="</"+"script> ";


str+="</body> \n";

document.write( str );
document.close();

parent.scroll(0,0);

var target_textarea;
var rec = null;
var target;
var back_text = "";

function load_action() {

	parent.focus();

	var iid = setInterval(function(){
		parent.focus();
		target_textarea = parent.document.activeElement;
		if ( (target_textarea.tagName).toLowerCase() == "textarea" ) {
			$("#check").text("textarea を取得しました");
			clearInterval(iid);
			$("#st_btn").prop("disabled", false);
			$("#ed_btn").prop("disabled", false);
		}
		else {
			$("#check").text("テキストエリアにカーソルを置いて下さい");
		}
	},500);

	if ( typeof webkitSpeechRecognition === 'undefined' ) {
		$("#info").text("使用できません");
		$("#st_btn").prop("disabled", true);
		$("#ed_btn").prop("disabled", true);
	}
	else {

		target = $("#first_text");

		// インスタンス作成
		rec = new webkitSpeechRecognition();
		// 初期設定
		rec.lang = "ja-JP";
		rec.interimResults = true;
		rec.continuous = true;
		// イベント登録
		rec.onerror = function(){
			$("#info").text("error");
		};
		rec.onnomatch = function(){
			$("#info").text("nomatch");
		};
		rec.onsoundstart = function(){
			$("#info").text("音検知");
		};
		rec.onsoundend = function(){
			$("#info").text("soundend");
		};
		rec.onspeechstart = function(){
			$("#info").text("スピーチ開始");
		};
		rec.onspeechend = function(){
			$("#info").text("スピーチ終了");
		};

		rec.onstart = function(){
			$("#info").text("開始");
		};
		rec.onend = function(){
			$("#info").text("終了");
		};
		// 結果テキストの作成
		rec.onresult = function(ev){
			var obj = ev.results;
			for (var i = ev.resultIndex; i < obj.length; i++ ) {
				if( obj[i].isFinal ) {
					target.text(obj[i][0].transcript);
					target = $("<div></div>");
					$("#result").append(target);
					target_textarea.value = back_text + $("#result").text();
				}
				else {
					target.text(obj[i][0].transcript);
				}
			}
		};	

		// ボタンイベント
		$("#st_btn").on("click",function(){

			back_text = target_textarea.value;

			rec.start();
			$("#st_btn").prop("disabled",true);
		})
		$("#ed_btn").on("click",function(){
			rec.stop();
			$("#st_btn").prop("disabled",false);
			$("#result").html("<div id=\"first_text\"></div>");
			target = $("#first_text");

		})
	}

}
途中、IE のチェックをしているところがありますが、汎用テンプレートを使用して作成しているからです。

改行を入れて読みやすくしたブックマークレットコード
javascript:
var%20wnd=document.createElement('iframe');
wnd.setAttribute('id','if');
wnd.frameBorder=0;
document.body.appendChild(wnd);
var%20url='';
if((location.href).substr(0,5)=='https'){
	url='https://lightbox.sakura.ne.jp/toolbox/recognition.js';
}else{
	url='http://toolbox.winofsql.jp/recognition.js';
}
wnd.contentWindow.document.write('<script src=\''+url+'\' charset=\'utf-8\'></script>')
最後の document.write は DOM でも書けますが、どうせ js のほうでは画面を作成するのに document.write を使用せざるを得ないので同じ事です。初期画面の HTML や JavaScript の文字列化はこちらから実行できます。
( プログラム用文字列 の JavaScript ボタン )


posted by lightbox at 2016-05-27 22:41 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

2016年05月22日


フリーフォントでボタン素材作成のバリエーションサンプル / ノーマル・文字なし・太枠・フォント

たくさんのフリーフォント(約260種類)を使用していろいろなボタンを簡単に作成できます。

▼ 以下は jQuery で実際に動作するコンテンツです



posted by lightbox at 2016-05-22 20:19 | WEBサービス | このブログの読者になる | 更新情報をチェックする

WindowBuilder のテーブルコントロールにインターネットから JSON データを読み込んで処理するテンプレート





インターネットからデータを読み込むのに、HttpGet というクラスをソースで同梱しています。プロジェクトのインポート方法は、『Eclipse 4.4 Pleiades + WindowBuilder テンプレート / アプリケーションウインドウとダイアログ』を参照して下さい。

JSON データを扱う Google Gson は、ライブラリとしては同梱しています。ダウンロードはこちら(GitHub のページ)です。※ ページ内の Gson Download のリンクからダウンロードページへ移動します

処理概要

1) ボタンをクリックすると、お天気Webサービス仕様 - Weather Hacks - livedoor 天気情報 の 『大阪の』JSON データを取得します。

2) 場所の名前と、地域コードを二つの列に表示し、行の内部コードとして URL を格納します

3) 行をダブルクリックすると、URL を使用してブラウザで開きます

ソースコード
import java.awt.Desktop;
import java.net.URI;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import com.google.gson.Gson;


public class TopWindow extends ApplicationWindow {

	private int width = 800;
	private int height = 600;
	private Table table;
	private Gson gson;

	// *********************************
	// コンストラクタ
	// *********************************
	public TopWindow() {
		super(null);
	}

	// *********************************
	// コントロールの追加
	// ※ Design での変更が反映されます
	// *********************************
	@Override
	protected Control createContents(Composite parent) {
		Composite container = new Composite(parent, SWT.NONE);

		// ボタンの定義
		Button button = new Button(container, SWT.NONE);
		// ボタンのイベント
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				
				// プログラム開始時に実行すると、固まるので直前に
				try {
					UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e1) {
					e1.printStackTrace();
				}
				
				// 確認ダイアログ( OK_CANCEL )の表示
				int result = JOptionPane.showConfirmDialog(
						null,
						"データを取得しますか",
						"確認",
						JOptionPane.OK_CANCEL_OPTION,
						JOptionPane.QUESTION_MESSAGE);
				// OK を選択
				if ( result == JOptionPane.OK_OPTION ) {
					// インターネットアクセス
					String data = HttpGet.execute("http://weather.livedoor.com/forecast/webservice/json/v1?city=270000", "utf-8");
					// データを取得できた
					if ( !data.equals("") ) {
						// コンソールで確認
						System.out.println(data);
						// JSON をオブジェクト化する為の GSON を作成
						gson = new Gson();
						// データに適合するプライベートクラスで変換
						Weather weatherData = gson.fromJson(data, Weather.class);
						// データ行数
						int length = weatherData.pinpointLocations.length;

						// 行データ格納用
						TableItem tableItem;
						// 列データ格納用
						String[] columnData = new String[2];
						for( int i = 0; i < length; i++) {
							// 確認用の表示
							System.out.println(String.format("name:%s, link:%s",
									weatherData.pinpointLocations[i].name,
									weatherData.pinpointLocations[i].link
								)
							);
							// 場所名
							columnData[0] = weatherData.pinpointLocations[i].name;
							// livedoor の個別コード
							columnData[1] = weatherData.pinpointLocations[i].link.replace("http://weather.livedoor.com/area/forecast/", "");
							// 行を Table から新しく取得
							tableItem = new TableItem(table, SWT.NONE);
							// 行に表示用の配列データをセット
							tableItem.setText(columnData);
							// livedoor の個別天気表示 URL を内部データとしてセット
							tableItem.setData(weatherData.pinpointLocations[i].link);
							
						}
					}
				}
			}
		});
		button.setBounds(10, 10, 81, 28);
		button.setText("実行");

		// Table の定義
		table = new Table(container, SWT.BORDER | SWT.FULL_SELECTION);
		table.addMouseListener(new MouseAdapter() {
			
			// テーブルをダブルクリック
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				int row_no = table.getSelectionIndex();
				// 行が内ばあいは row_no は -1
				System.out.println( String.format("row_no : %d",row_no) );
				// 行データがあり、任意の行の上でダブルクリックした場合
				if ( row_no >= 0 ) {
					// タイトル部分の表示
					TableColumn tableColumn;
					tableColumn = table.getColumn(0);
					System.out.println( tableColumn.getText() );
					tableColumn = table.getColumn(1);
					System.out.println( tableColumn.getText() );

					// 行部分の表示
					TableItem tableItem = table.getItem(row_no);
					// 名前の表示
					System.out.println( tableItem.getText(0) );
					// コードの表示
					System.out.println( tableItem.getText(1) );
					// URL の表示
					System.out.println( tableItem.getData() );
					
					// プログラム開始時に取得すると、固まるので直前に
					// ブラウザを開く
					Desktop desktop = Desktop.getDesktop();
					try {
						URI uri = new URI((String) tableItem.getData());
						desktop.browse(uri);
					} catch (Exception ex) {
						ex.printStackTrace();
					}				
					
				}
			}
		});
		table.setBounds(10, 50, 764, 498);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		
		// 列の作成
		TableColumn tableColumn = new TableColumn(table, SWT.NONE);
		tableColumn.setWidth(100);
		tableColumn.setText("名前");

		TableColumn tableColumn_1 = new TableColumn(table, SWT.NONE);
		tableColumn_1.setWidth(131);
		tableColumn_1.setText("コード");


		return container;
	}

	// *********************************
	// アプリケーションの開始
	// *********************************
	public static void main(String args[]) {
		try {
			// 自分自身(TopWindow) の作成
			TopWindow window = new TopWindow();
			// open を実行したら、Window を閉じるまで次の行を実行しない
			window.setBlockOnOpen(true);
			window.open();
			// Window を閉じたら以下を実行してアプリケーションを終了する
			Display.getCurrent().dispose();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// *********************************
	// Window の初期設定
	// *********************************
	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);

		// タイトルの設定
		newShell.setText("タイトル文字列");

		// アイコンの設定
		ImageData id = new ImageData("image/lightbox.png");
		Image img = new Image(newShell.getDisplay(), id);
		newShell.setImage(img);

	}

	// *********************************
	// Window サイズの初期設定
	// *********************************
	@Override
	protected Point getInitialSize() {
		// プライベート変数を使用してウインドウサイズを決定しています
		return new Point(width, height);
	}
	
	// Livedoor の お天気Webサービス用 (配列データ用)
	private class PinpointLocation {
		String link;
		String name;
		public PinpointLocation(String myLink, String myName) {
			name = myName;
			link = myLink;
		}

		@Override
		public String toString() {
			return name;
		}
	}
	// Livedoor の お天気Webサービス用 (JSON用)
	private class Weather {
		PinpointLocation[] pinpointLocations;
	}	
}

どのような環境でも発生するのかどうかわかりませんが、UIManager.setLookAndFeel の実行場所によって、JOptionPane のメッセージボックスで固まったり、Desktop.getDesktop() の実行場所によっても固まったりしたので、変数の置き場所を実行ブロック内にしています。



posted by lightbox at 2016-05-22 19:10 | java : WindowBuilder | このブログの読者になる | 更新情報をチェックする

2016年05月21日


Android の Spinner に関するいろいろな実装と知識 / Android Studio

Android の Spinner は、一般的にはコンボボックスと言われるものと同様で、何も指定しなければ以下のような動作をします。



Spinner には、spinnerMode というプロパティがあり、デフォルトでは MODE_DROPDOWN として動作しています。( XML で定義せずに、インスタンスを作成する場合は、コンストラクタで指定できます )



この部分を MODE_DIALOG に変更すると、以下のように動作します



リスト部分の実装について

リスト部分は、一般的なリストビューと同じです。ArrayAdapter を使用します。単純に一つの TextView を持つ、Android で定義済みの simple_spinner_dropdown_item を使って実装しています。( simple_spinner_dropdown_item である必要はありません )
package lightbox.may.combobox;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

	// ******************************
	// 文字列配列 Spinner
	// ******************************
	private ArrayAdapter<String> adapter;
	private Spinner spinner;
	private String[] list_data = {"大阪","東京","愛知","岡山"};
	private String[] list_value = {"27","13","23","33"};

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

		// 配列を格納して Android のリストを表示する ArrayAdapter クラス
		// レイアウトは Android で定義されたもの。
		// TextView を継承したクラスであれば自前のレイアウトで OK
		adapter = new ArrayAdapter(
			MainActivity.this,
			android.R.layout.simple_spinner_dropdown_item);

		// Spinner のインスタンスを取得
		spinner = (Spinner) MainActivity.this.findViewById(R.id.spinner);

		// ArrayAdapter に配列を格納
		adapter.addAll(list_data);

		// Spinner に ArrayAdapter をセット
		spinner.setAdapter(adapter);

		// ボタンの インスタンスを取得
		Button button = (Button) MainActivity.this.findViewById(R.id.button);
		// アルファベットの小文字を反映できるようにする
		button.setAllCaps(false);
		// ボタンのイベントの定義
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// ******************************************
				// Spinner より選択されているテキストを取得
				// ******************************************

				// simple_spinner_dropdown_item に定義されている id から
				String text = ((TextView)(MainActivity.this.findViewById(android.R.id.text1))).getText().toString();
				Log.i("lightbox", text);

				// sppiner から
				text = (String) spinner.getSelectedItem();
				Log.i("lightbox", text);

				// ポジション番号から、用意しておいた配列を使用して取り出す
				int pos = spinner.getSelectedItemPosition();
				Log.i("lightbox", list_data[pos]);

			}
		});


	}
}

Spinner とは関係ありませんが、setAllCaps でボタンの文字が全て大文字にならないようにしています。

Spinner の情報の取り出し

ここでは、Spinner に表示されるテキストを取り出しています。しかし、実際は Spinner の選択 されたインデックスより、テキストの元となるコードを list_value より取り出すのが正解です。ですが、これは最も簡単なサンプルとして、ArrayAdapter に 文字列の配列を引き渡しているからそうなるのであって、本来は専用クラスを作成し、その配列を最初に渡しておいて、その中の値を直接取り出すのが汎用的になります。

Spinner 用のクラスを作成して利用する
package lightbox.may.combobox;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

public class MainActivity extends AppCompatActivity {

	// ******************************
	// MyData 配列 Spinner
	// ******************************
	private ArrayAdapter<MyData> adapter;

	// セットする情報の配列
	private MyData[] my_data = {
		new MyData("大阪","27"),
		new MyData("東京","13"),
		new MyData("愛知","23"),
		new MyData("岡山","33")} ;

	// Spinner のインスタンス
	private Spinner spinner;

	// 情報格納用のクラス
	private class MyData {
		// 表示される文字列用
		private String myString = null;
		// 内部コード
		private String myValue = null;

		// コンストラクタ
		public MyData(String myString,String myValue) {
			this.myString = myString;
			this.myValue = myValue;
		}

		// 値取得用
		String getValue() {
			return myValue;
		}

		// ArrayAdapter の仕様に合わせて toString を 上書きしておく
		@Override
		public String toString() {
			return myString;
		}
	}

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

		// 配列を格納して Android のリストを表示する ArrayAdapter クラス
		// レイアウトは Android で定義されたもの。
		// TextView を継承したクラスであれば自前のレイアウトで OK
		adapter = new ArrayAdapter(
			MainActivity.this,
			android.R.layout.simple_spinner_dropdown_item);

		// Spinner のインスタンスを取得
		spinner = (Spinner) MainActivity.this.findViewById(R.id.spinner);

		// ArrayAdapter に MyData 配列を格納
		adapter.addAll(my_data);

		// Spinner に ArrayAdapter をセット
		spinner.setAdapter(adapter);

		// ボタンの インスタンスを取得
		Button button = (Button) MainActivity.this.findViewById(R.id.button);
		// アルファベットの小文字を反映できるようにする
		button.setAllCaps(false);
		// ボタンのイベントの定義
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// ******************************************
				// Spinner より選択されている情報を取得
				// ******************************************
				// sppiner から MyData を取得
				MyData md = (MyData) spinner.getSelectedItem();
				// 内部コードの取得
				Log.i("lightbox", md.getValue());
				// テキストの取得
				Log.i("lightbox", md.toString());

			}
		});


	}
}

データをセットするのに、addAll を使用しているのは、インターネット経由で JSON を使用して読み込む事が通常想定されるので、一括となっています。

リストの行の表示のカスタマイズ

これらのサンプルでは、画面定義は simple_spinner_dropdown_item を使用していますが、単純に TextView のみの画面定義をして利用可能です。


<?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="match_parent"
          android:textSize="40dp"
          android:padding="10dp">

</TextView>

完全にカスタマイズするには

Spinner の見え方は、閉じた一つの View と リストで表示されるビューと二つあります。また、二つ以上のコントロールのある View を作った場合は ArrayAdapter を継承したクラスを作成して利用する必要があります。それらの機能を汎用的に実装したのが以下の SpinnerArrayAdapter です。
package lightbox.may.combobox;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

/**
 * Created by lightbox on 2016/05/21.
 */
public class SpinnerArrayAdapter<T> extends ArrayAdapter<T> {

	public interface OnGetViewListener {
		abstract public View onGetViewListener(int position, View convertView, ViewGroup parent);
	}

	private OnGetViewListener listener = null;
	private OnGetViewListener listener_drop_down = null;

	public SpinnerArrayAdapter(Context context, int resource, OnGetViewListener listener, OnGetViewListener listener_drop_down) {
		super(context, resource);
		this.listener = listener;
		this.listener_drop_down = listener_drop_down;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if ( listener != null ) {
			return listener.onGetViewListener(position, convertView, parent);
		}
		return super.getView(position, convertView, parent);
	}

	@Override
	public View getDropDownView(int position, View convertView, ViewGroup parent) {
		if ( listener != null ) {
			return listener_drop_down.onGetViewListener(position, convertView, parent);
		}
		return super.getDropDownView(position, convertView, parent);
	}
}


画面定義 / my_spinner_custom
<?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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:textSize="40dp"
        android:padding="10dp"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView2"
        android:textSize="20dp"
        android:padding="5dp"/>
</LinearLayout>



使用方法
package lightbox.may.combobox;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

	// ******************************
	// MyData 配列 Spinner
	// ******************************
	private SpinnerArrayAdapter <MyData> adapter;

	// セットする情報の配列
	private MyData[] my_data = {
		new MyData("大阪","27"),
		new MyData("東京","13"),
		new MyData("愛知","23"),
		new MyData("岡山","33")} ;

	// Spinner のインスタンス
	private Spinner spinner;

	// 情報格納用のクラス
	private class MyData {
		// 表示される文字列用
		private String myString = null;
		// 内部コード
		private String myValue = null;

		// コンストラクタ
		public MyData(String myString,String myValue) {
			this.myString = myString;
			this.myValue = myValue;
		}

		// 値取得用
		String getValue() {
			return myValue;
		}

		// ArrayAdapter の仕様に合わせて toString を 上書きしておく
		@Override
		public String toString() {
			return myString;
		}
	}

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

		// my_spinner_custom を使用したカスタマイズ
		adapter = new SpinnerArrayAdapter<MyData>(
			MainActivity.this,
			R.layout.my_spinner_custom,
			// リストでは無い表示部分
			new SpinnerArrayAdapter.OnGetViewListener() {
				@Override
				public View onGetViewListener(int position, View convertView, ViewGroup parent) {

					View rowView = convertView;
					if (rowView == null) {
						// 現在の View の取得
						LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService
							(Context.LAYOUT_INFLATER_SERVICE);
						rowView = inflater.inflate(R.layout.my_spinner_custom, null);
					}

					// Adapter にセットされているこのポジションの MyData を取得
					MyData md = adapter.getItem(position);

					// my_spinner_custom 内の TextView にデータをセット
					TextView tv1 = (TextView) rowView.findViewById(R.id.textView);
					tv1.setText(md.toString());
					TextView tv2 = (TextView) rowView.findViewById(R.id.textView2);
					tv2.setText(md.getValue());

					return rowView;
				}
			},
			// リストの表示部分
			new SpinnerArrayAdapter.OnGetViewListener() {
				@Override
				public View onGetViewListener(int position, View convertView, ViewGroup parent) {
					View rowView = convertView;
					if (rowView == null) {
						// 現在の View の取得
						LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService
							(Context.LAYOUT_INFLATER_SERVICE);
						rowView = inflater.inflate(R.layout.my_spinner_custom, null);
					}

					// Adapter にセットされているこのポジションの MyData を取得
					MyData md = adapter.getItem(position);

					// my_spinner_custom 内の TextView にデータをセット
					TextView tv1 = (TextView) rowView.findViewById(R.id.textView);
					tv1.setText(md.toString());
					TextView tv2 = (TextView) rowView.findViewById(R.id.textView2);
					tv2.setText(md.getValue());

					return rowView;
				}
		});

		// Spinner のインスタンスを取得
		spinner = (Spinner) MainActivity.this.findViewById(R.id.spinner);

		// ArrayAdapter に MyData 配列を格納
		adapter.addAll(my_data);

		// Spinner に ArrayAdapter をセット
		spinner.setAdapter(adapter);

		// ボタンの インスタンスを取得
		Button button = (Button) MainActivity.this.findViewById(R.id.button);
		// アルファベットの小文字を反映できるようにする
		button.setAllCaps(false);
		// ボタンのイベントの定義
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// ******************************************
				// Spinner より選択されている情報を取得
				// ******************************************
				// sppiner から MyData を取得
				MyData md = (MyData) spinner.getSelectedItem();
				// 内部コードの取得
				Log.i("lightbox", md.getValue());
				// テキストの取得
				Log.i("lightbox", md.toString());

			}
		});


	}
}


関連するソースコード

ArrayAdapter

simple_spinner_dropdown_item.xml



posted by lightbox at 2016-05-21 18:28 | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2016年05月18日


kintone で画像を表示する / PC と スマホで少し違います。PC ではスペース項目、スマホでは、スマホ用ヘッダスペースを使用します



一応動的に画像の HTML を組み込む方法は、『kintoneのレコード詳細ページからAmazon商品データを参照するテクニック』に記述されています。ただ、この解説ではスマホは対応していません。ですが、単純にコードから URL を作成して商品画像表示するだけならば、以下のようにすれば簡単に実装できます。

PC 用 JavaScript
// *****************************************
// (function(){実行コード})() は JavaSript 
// におけるブロックの実行
// *****************************************
(function() {
	"use strict";

	kintone.events.on('app.record.detail.show', function(event){

		// スペース
		var Space_LargeImg = kintone.app.record.getSpaceElement('Large_Image');
		// event 内のレコード情報より
		var No_Image = event.record.No_Image.value;

		// スペースのレイアウト幅を画像が超え無いようにする
		var image_css = '<style>.user_image {max-width: 200px; height: auto;}</style>';

		// 画像表示
		Space_LargeImg.innerHTML = image_css + '<img class="user_image" src="http://winofsql.jp/image/test/' + No_Image + '.png">';

	});

})();

フォームの編集で、画像表示用の『スペース』を設置しておきます。これは、PC でのみ有効で、設定できる内容は、JavaScript から参照できる 要素ID のみとなります。なので、ここは英数字で『Large_Image』と定義しています。また、画像が大きいとフォームレイアウトが崩れるので、固定で 200px に設定しています。





スマホ 用 JavaScript
// *****************************************
// (function(){実行コード})() は JavaSript 
// におけるブロックの実行
// *****************************************
(function() {
	"use strict";

	kintone.events.on('mobile.app.record.detail.show', function(event){

		// スマホ用ヘッダスペース
		var Space_LargeImg = kintone.mobile.app.getHeaderSpaceElement();
		// event 内のレコード情報より
		var No_Image = event.record.No_Image.value;

		// デバイスの最大幅を画像が超え無いようにする
		var image_css = '<style>.user_image {max-width: 100%; height: auto;}</style>';

		// 画像表示
		Space_LargeImg.innerHTML = image_css + '<img class="user_image" src="http://winofsql.jp/image/test/' + No_Image + '.png">';

	});

})();

スマホでは、スペース項目は使用できませんが、ヘッダの下を自由に使えるのでそこに画像を表示します。また、最大幅を 100% にする事によって、大きな画像は横幅いっぱいで、スマホの表示幅より小さい画像はそのまま表示されます。最初の一覧で表示される項目は、アプリの設定画面の『レコードタイトル』で選択します

  


関連する kintone ドキュメント

PC画面で使用できるAPI,スマートフォンのみで利用できるAPI,両方で利用できるAPIをまとめた表





posted by lightbox at 2016-05-18 14:34 | kintone | このブログの読者になる | 更新情報をチェックする
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 終わり