忍者ブログ

2007/03/04開始。ソフトウェア管理やDelerer SEの作者であるおにぎりくんの試行錯誤の記録です。
2024
前の月へ 10 : 123456789101112131415161718192021222324252627282930 : 12 次の月へ
1  2  3  4  5  6 
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

ダイアログのためにxmlを書くのは嫌なので、 コードで書く方法を調べた。

Android : How to update the selector(StateListDrawable) programmatically

http://stackoverflow.com/questions/5092649/android-how-to-update-the-selectorstatelistdrawable-programmatically

ここによると、StateListDrawableクラスを作成し、addStateメソッドでDrawableオブジェクトを追加してくださいとのこと。状態はandroid.R.attr.state_hogehogeで指定するのだが、何もない状態はマイナスにするといいらしい。

PR

前回の記事のものに手を加えました。縦横の画面サイズ切り替えで表示を維持したり、コードからビューを追加してみたりしています。また、名前がアレだったので直しました。


プロジェクト一式ダウンロード

HorizontalPageScrollView.java

package fsoriented.sample.horizontalscroll;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

/**
 * ページごとにスナップする横方向のスクロールビュー。
 *
 * フリック(flingイベント)によって、隣のページにスナップする。
 * ドラッグ(upイベント)によって、一番近いページにスナップする。
 *
 * Gelleryでも似たようなことができそうなんだけど。。。
 *
 * 内部にLinearLayout(horizontal)を持たせることを期待している。
 * LinearLayout直下のビューをページとし、勝手にサイズを変更する。
 *
 * 参考:
 *  - http://www.adamrocker.com/blog/292/we-are-the-speaker-of-google-devfest-2010-japan.html
 *  - http://blog.global-eng.co.jp/android/2011/02/18/horizontalscrollviewにイージングをつける方法/
 *  - http://android.keicode.com/basics/ui-custom-horizontalscrollview.php
 *
 * @author LapisCactus
 *
 */
public class HorizontalPageScrollView extends HorizontalScrollView implements OnGestureListener {

	/** フリックを検出するオブジェクト */
	private GestureDetector detector;
	/** フリックとみなさない速度の閾値 */
	private final float velocityThreshold = 100f;
	/** 現在のページ */
	private int currentPage = 0;
	/** ページ遷移時に呼ばれるリスナー。nullなら呼ばない。 */
	private OnPageChangeListener listener = null;

	/**
	 * コンストラクタ
	 *
	 * @param context
	 */
	public HorizontalPageScrollView(Context context) {
		super(context);
		initialize(context);
	}

	/**
	 * コンストラクタ
	 *
	 * @param context
	 * @param attrs
	 */
	public HorizontalPageScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initialize(context);
	}

	// フリックを検出するオブジェクトを生成する
	private void initialize(Context context) {
		detector = new GestureDetector(context, this);
		this.setFadingEdgeLength(0);
		this.setHorizontalScrollBarEnabled(false);
	}

	/**
	 * 現在表示されているページ番号を返す
	 *
	 * @return ページ番号
	 */
	public int getCurrentPage() {
		return currentPage;
	}

	/**
	 * 指定したページを表示する
	 *
	 * @param page
	 *            ページ番号
	 * @param event
	 *            ページ遷移イベントを発生させるかどうか
	 */
	public void setCurrentPage(int page, boolean event) {
		// サイズが確定していれば、表示位置を移動する
		int viewWidth = this.getWidth();
		if (viewWidth != 0) {
			scrollTo(page * viewWidth, 0);
		}
		// 現在ページを更新する。サイズが未確定なら、確定時イベント(onLayout)で現在ページへ移動する
		currentPage = page;
		// ページ遷移イベントを送信する
		if (event && listener != null) {
			listener.onPageChanged(currentPage, ((LinearLayout) getChildAt(0))
					.getChildAt(currentPage));
		}
	}

	/**
	 * ページ遷移時に呼ばれるリスナーを登録する。
	 *
	 * @param listener
	 */
	public void setOnPageChangedListener(OnPageChangeListener listener) {
		this.listener = listener;
	}

	// ビューのサイズが変更されたときの処理
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		// ページの幅と高さを設定する
		int count = ((LinearLayout) getChildAt(0)).getChildCount();
		for (int i = 0; i < count; i++) {
			((LinearLayout) getChildAt(0)).getChildAt(i).setLayoutParams(
					new android.widget.LinearLayout.LayoutParams(w, h));
		}
	}

	// レイアウトされたときの処理
	// currentPageの適用はここで行う。
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		// カレントページに移動
		int w = r - l;
		smoothScrollTo(currentPage * w, 0);
	}

	// 画面にタッチしたときの処理
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// フリック判定を優先して行う
		if (detector.onTouchEvent(event))
			return true;

		// フリックでなければ、指が離れたイベントを使用する
		switch (event.getAction()) {
		case MotionEvent.ACTION_UP:

			// もっとも近い境界へスナップする
			int currentx = this.getScrollX();
			int viewWidth = this.getWidth();
			int destPage = (currentx + viewWidth / 2) / viewWidth;
			smoothScrollTo(destPage * viewWidth, 0);
			if (currentPage != destPage) {
				currentPage = destPage;
				listener.onPageChanged(currentPage, ((LinearLayout) getChildAt(0))
						.getChildAt(currentPage));
			}
			return true;
		}

		// そのほかはデフォルト
		return super.onTouchEvent(event);
	}

	// フリック時の処理
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
		// フリックなら隣に移動
		int currentx = this.getScrollX();
		int viewWidth = this.getWidth();
		if (velocityX < -velocityThreshold) {
			// 右ページ
			int destPage = currentx / viewWidth + 1;
			smoothScrollTo(destPage * viewWidth, 0);
			if (destPage < ((LinearLayout) getChildAt(0)).getChildCount()) {
				currentPage = destPage;
				listener.onPageChanged(currentPage, ((LinearLayout) getChildAt(0))
						.getChildAt(currentPage));
			}
			return true;
		} else if (velocityX > velocityThreshold) {
			// 左ページ
			int destPage = currentx / viewWidth;
			smoothScrollTo(destPage * viewWidth, 0);
			if (destPage >= 0 && destPage != currentPage) {
				currentPage = destPage;
				listener.onPageChanged(currentPage, ((LinearLayout) getChildAt(0))
						.getChildAt(currentPage));
			}
			return true;
		}
		return false;
	}

	// 不使用
	public boolean onDown(MotionEvent e) {
		return false;
	}

	// 不使用
	public void onLongPress(MotionEvent e) {
	}

	// 不使用
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
		return false;
	}

	// 不使用
	public void onShowPress(MotionEvent e) {
	}

	// 不使用
	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}

	/**
	 * フリックやドラッグにより、ページが遷移したときに呼ばれるコールバック定義
	 *
	 * @author LapisCactus
	 *
	 */
	public static interface OnPageChangeListener {
		/**
		 * ページが遷移したときの処理
		 *
		 * @param pageIndex
		 *            ページ番号(0~)
		 * @param showing
		 *            表示中のViewオブジェクト
		 */
		public abstract void onPageChanged(int pageIndex, View showing);
	}
}

ギャラリーのような横スクロールビューです。 ページごとにスナップします。


プロジェクトファイルダウンロード

2011/05/06追記:ファイルを差し替えました。新しく記事を書きました(ページ毎にスナップする横スクロールビュー(2))。

フォントを読み込むサンプル。 意外と簡単にフォントを読み込んでくれる。


MainActivity.java

package sample.customfont;

import java.io.File;

import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.TextView;

/**
 * フォントをSDカードから読み込み、TextViewに適用するサンプル。
 *
 * フォントファイルをファイルパスで指定し、読み込む。
 * ファイルが見つからなければ、フォントを適用しない。
 * フォントファイルの読み込みは簡単で、ただ
 *   Typeface.createFromFile(File)
 * を使うだけである。
 * ファイルが読み込めないときに、例外RuntimeExceptionが投げられる。
 *   E/AndroidRuntime( 1000): java.lang.RuntimeException:
 *   Unable to start activity ComponentInfo{sample.customfont/sample.customfont.MainActivity}:
 *   java.lang.RuntimeException: native typeface cannot be made
 * (DDMSを使ってフォントファイルを転送しようとしたが、失敗していたため例外が起きた。
 * adb pushを使うと上手くいくのだが。。。)
 *
 * @author LapisCactus
 *
 */
public class MainActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// load UI widgets
		TextView textview = (TextView) findViewById(R.id.main_text);

		// load a font and apply it to a TextView
		File file = new File("/mnt/sdcard/fonts/KozGoPro-Light.otf");
		System.out.println("exists:  " + file.exists());
		System.out.println("canRead: " + file.canRead());
		if (file.exists() && file.canRead()) {
			Typeface tf = Typeface.createFromFile(file);
			textview.setTypeface(tf);
		}
	}

}

Android記事へのリンク

導入と日常的に使うもの。

開発環境構築

http://www.usefullcode.net/2010/12/android_sdk_inst01.html
>JDK、Android SDK、ADT、NDK

 

公式リファレンス(内容は英語)

http://developer.android.com/intl/ja/reference/packages.html
>右上の検索ボックスにクラス名入力+出てくる候補クリック

 

公式開発ガイドの私訳(日本語)

https://sites.google.com/a/techdoctranslator.com/jp/home
>公式の開発ガイドと項目が同じで使いやすい

 

スポンサード・リンク
フリーソフト指向::開発日記 by LapisCactus
忍者ブログ | [PR]

今日の聖書
自己紹介
名前:
LapisCactus (おにぎりくん)
Twitter:
Mail:
onigirikun_hsp@hotmail.com
自己紹介:
ふつうのしすてむえんじにあ。
趣味で「ソフトウェア管理」や
「TextView」を作っています。
仕事でもコンピュータを触っているのに
趣味も同じという。
健康に悪いですね。
カレンダー
10 2024/11 12
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
ブログ内検索
最新CM
[03/03 kusakari]
[11/12 おにぎりくん]
[11/08 れい]
アクセス解析