Honeycombチュートリアル その3

Fragmentを追加する

前回作成したアプリにフラグメントを追加する。

FragmentもViewやActivityと同様にレイアウトリソースを使用することができる。ここではFragmentに設定するカスタムViewとレイアウトを作成する。

手順

  1. Fragmentに配置するためのViewを作成する
    1. FitCenterFrameLayout.java
  2. レイアウトファイルの作成
    1. content_wellcome.xml
  3. 画像表示用のFragmentを作成する
    1. ContentFragment.java
  4. add to setting when the LongClick the fragment.

画像表示のカスタムViewを作成する

=============================================

ViewGroupを継承した独自Viewを作成する。
                                                                                              • -

画像表示のカスタムView**FitCenterFrameLayout**を作成する
内容は複雑なのでSampleからそのままコピペでOK。

クリック、ロングクリックようのセレクターを作成。
                                                                                              • -

ここもコピペでOK

コピペ手順

  • セレクタ保存用のディレクトリ drawableを作成する。
  • サンプルからpicture_frame.xmlファイルをコピペ
  • その他のセレクタ用の画像をコピペ
    • picture_frame_default.9.png
    • picture_frame_pressed.9.png
    • picture_frame_selected.9.png
FitCenterFrameLayout.java
                                                    • -
	package com.hidecheck.honeycomic;
	
	import android.content.Context;
	import android.util.AttributeSet;
	import android.view.View;
	import android.view.ViewGroup;
	
	public class FitCenterFrameLayout extends ViewGroup {
	
		public FitCenterFrameLayout(Context context) {
			super(context);
		}
	
		public FitCenterFrameLayout(Context context, AttributeSet attrs) {
			super(context, attrs);
		}
		
		@Override
		protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	        // We purposely disregard child measurements.
	        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
	        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
	        setMeasuredDimension(width, height);
	
	        int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
	        int childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED);
	
	        int childCount = getChildCount();
	        for (int i = 0; i < childCount; i++) {
	            getChildAt(i).measure(childWidthSpec, childHeightSpec);
	        }
		}
	
		@Override
		protected void onLayout(boolean changed, int l, int t, int r, int b) {
	        final int childCount = getChildCount();
	
	        final int parentLeft = getPaddingLeft();
	        final int parentTop = getPaddingTop();
	        final int parentRight = r - l - getPaddingRight();
	        final int parentBottom = b - t - getPaddingBottom();
	
	        final int parentWidth = parentRight - parentLeft;
	        final int parentHeight = parentBottom - parentTop;
	
	        int unpaddedWidth, unpaddedHeight, parentUnpaddedWidth, parentUnpaddedHeight;
	        int childPaddingLeft, childPaddingTop, childPaddingRight, childPaddingBottom;
	
	        for (int i = 0; i < childCount; i++) {
	            final View child = getChildAt(i);
	            if (child.getVisibility() == GONE) {
	                continue;
	            }
	
	            // Fit and center the child within the parent. Make sure not to consider padding
	            // as part of the child's aspect ratio.
	
	            childPaddingLeft = child.getPaddingLeft();
	            childPaddingTop = child.getPaddingTop();
	            childPaddingRight = child.getPaddingRight();
	            childPaddingBottom = child.getPaddingBottom();
	
	            unpaddedWidth = child.getMeasuredWidth() - childPaddingLeft - childPaddingRight;
	            unpaddedHeight = child.getMeasuredHeight() - childPaddingTop - childPaddingBottom;
	
	            parentUnpaddedWidth = parentWidth - childPaddingLeft - childPaddingRight;
	            parentUnpaddedHeight = parentHeight - childPaddingTop - childPaddingBottom;
	
	            if (parentUnpaddedWidth * unpaddedHeight > parentUnpaddedHeight * unpaddedWidth) {
	                // The child view should be left/right letterboxed.
	                final int scaledChildWidth = unpaddedWidth * parentUnpaddedHeight
	                        / unpaddedHeight + childPaddingLeft + childPaddingRight;
	                child.layout(
	                        parentLeft + (parentWidth - scaledChildWidth) / 2,
	                        parentTop,
	                        parentRight - (parentWidth - scaledChildWidth) / 2,
	                        parentBottom);
	            } else {
	                // The child view should be top/bottom letterboxed.
	                final int scaledChildHeight = unpaddedHeight * parentUnpaddedWidth
	                        / unpaddedWidth + childPaddingTop + childPaddingBottom;
	                child.layout(
	                        parentLeft,
	                        parentTop + (parentHeight - scaledChildHeight) / 2,
	                        parentRight,
	                        parentTop + (parentHeight + scaledChildHeight) / 2);
	            }
	        }
	
		}
	
	}

レイアウトファイルの作成

===============================
Fragmentに設定するレイアウトファイルの作成する

  • タグを使用しclassプロパティに作成したカスタムViewを指定する。
  • ImageViewのbackgroundプロパティにセレクターを指定する
content_wellcom.xml
                                                    • -
    <?xml version="1.0" encoding="utf-8"?>
    <view
        xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.hidecheck.honeycomic.FitCenterFrameLayout"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="24dp"
        android:clickable="true">
    
        <ImageView
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:id="@+id/image"
            android:duplicateParentState="true"
            android:background="@drawable/picture_frame"
            android:layout_gravity="center"></ImageView>
    
    </view>

Fragmentの作成

=============================================

Fragmentのデザインレイアウトを作成する
                                                                                  • -

上記で作成したカスタムViewを持ったレイアウトファイルを作成する

画像表示をするFragmentを作成する
                                                                    • -

フラグメントを作成するには、Fragmentのサブクラスを作成する必要があります。
作成したFragmentにレイアウトを適用させるにはLayoutInflater#inflateで引数にレイアウトリソースを指定する。
Activityのレイアウトファイルにfragmentタグを追加する

  1. ContentFragmentの作成
    1. 以下のfieldを追加する
      1. private View contentView;
      2. private Bitmap bitmap = null;
    2. 以下のメソッドをオーバライドする
      1. onCreateView
      2. onActivityCreated
  2. main.xmlを以下のように修正する
    1. TextViewの削除
    2. ContentFragmentの追加
ContentFragment.java
                                          • -
	package com.hidecheck.honeycomic;
	
	import android.app.Fragment;
	import android.graphics.Bitmap;
	import android.graphics.BitmapFactory;
	import android.os.Bundle;
	import android.view.LayoutInflater;
	import android.view.View;
	import android.view.ViewGroup;
	import android.widget.ImageView;
	
	public class ContentFragment extends Fragment {
		private View contentView;
		
		//The bitmap currently used by ImageView
		private Bitmap bitmap = null;
		
		@Override
		public void onActivityCreated(Bundle savedInstanceState) {
			super.onActivityCreated(savedInstanceState);
		}
	
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
			contentView = inflater.inflate(R.layout.content_wellcome, null);
			final ImageView imageView  = (ImageView)contentView.findViewById(R.id.image);
			contentView.setDrawingCacheEnabled(false);
	
			// TODO change image resource. this operation will be deleted later.
			bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.big_droid);
			imageView.setImageBitmap(bitmap);
	
			return contentView;
		}
		
	}
main.xml
                                          • -
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:id="@+id/flags"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <fragment
            class="com.hidecheck.honeycomic.ContentFragment"
            android:id="@+id/frag_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
実行結果
                                • -

.. image:: images/create_fragment01.png
:scale: 60

System Barを表示したり、消したりする

==============================================
画像をクリックしてSystem Barの表示、非表示を行う

手順
                                  • -
  1. change onCreateView
    1. setOnSystemUiVisibilityChangeListener
    2. setOnClickListener
    3. ImageView setImage from resouce and after changing.
onCreateViewの修正
                                          • -
表示状態の制御

Fragment#setSystemUiVisibilityメソッドを使って、System Barの表示状態を制御する

Status Values

STATUS_BAR_VISIBLE 表示
STATUS_BAR_HIDDEN 非表示
		contentView.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if(contentView.getSystemUiVisibility() == View.STATUS_BAR_VISIBLE){
					contentView.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
				}else{
					contentView.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
				}
			}
		});
表示状態変更イベントのハンドリング

表示状態の変更通知を受け取るようにするにはsetOnSystemUiVisibilityChangeListenerでOnSystemUiVisibilityChangeListenerを登録する。

ActionBarの表示状態をSystemBarと同期させるためActionBar#show() ActionBar#hide()メソッドを実行する。

		contentView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
			
			@Override
			public void onSystemUiVisibilityChange(int visibility) {
				ActionBar actionBar = activity.getActionBar();
				if(actionBar != null){
					contentView.setSystemUiVisibility(visibility);
					if(visibility == View.STATUS_BAR_VISIBLE){
						actionBar.show();
					}else{
						actionBar.hide();
					}
				}
			}
		});
ContentFragment.java
                                          • -
	package com.hidecheck.honeycomic;
	
	import android.app.ActionBar;
	import android.app.Activity;
	import android.app.Fragment;
	import android.graphics.Bitmap;
	import android.graphics.BitmapFactory;
	import android.os.Bundle;
	import android.view.LayoutInflater;
	import android.view.View;
	import android.view.View.OnClickListener;
	import android.view.View.OnSystemUiVisibilityChangeListener;
	import android.view.ViewGroup;
	import android.widget.ImageView;
	
	public class ContentFragment extends Fragment {
		private View contentView;
		
	    // The bitmap currently used by ImageView
	    private Bitmap bitmap = null;

		@Override
		public void onActivityCreated(Bundle savedInstanceState) {
			super.onActivityCreated(savedInstanceState);
		}
	
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
			contentView = inflater.inflate(R.layout.content_wellcome, null);
			final ImageView imageView  = (ImageView)contentView.findViewById(R.id.image);
			contentView.setDrawingCacheEnabled(false);
	
			// TODO setting DragListener later
			
	        // Keep the action bar visibility in sync with the system status bar. That is, when entering
	        // 'lights out mode,' hide the action bar, and when exiting this mode, show the action bar.
			final Activity activity = getActivity();
			contentView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
				
				@Override
				public void onSystemUiVisibilityChange(int visibility) {
					ActionBar actionBar = activity.getActionBar();
					if(actionBar != null){
						contentView.setSystemUiVisibility(visibility);
						if(visibility == View.STATUS_BAR_VISIBLE){
							actionBar.show();
						}else{
							actionBar.hide();
						}
					}
				}
			});
	
			contentView.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					if(contentView.getSystemUiVisibility() == View.STATUS_BAR_VISIBLE){
						contentView.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
					}else{
						contentView.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
					}
				}
			});
			
			// TODO change image resource
			imageView.setImageResource(R.drawable.big_droid);
			return contentView;
		}
		
	}
実行結果
                                • -


イメージをクリックする