2007/03/04開始。ソフトウェア管理やDelerer SEの作者であるおにぎりくんの試行錯誤の記録です。
- [Vue.js]時計?タイムコードを表示するWebアプリ
- (2021/11/16)
- ポエム
- (2020/09/30)
- メトロノームアプリをリリース
- (2017/04/22)
- Sikulix勉強中:便利関数
- (2017/02/25)
- [JavaFX]学習メモ
- (2016/09/22)
ダイアログのためにxmlを書くのは嫌なので、 コードで書く方法を調べた。
Android : How to update the selector(StateListDrawable) 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://developer.android.com/intl/ja/reference/packages.html>右上の検索ボックスにクラス名入力+出てくる候補クリック
スポンサード・リンク
フリーソフト指向::開発日記 by LapisCactus