読者です 読者をやめる 読者になる 読者になる

うさがにっき

読書感想文とプログラムのこと書いてきます

Androidでショーケースレイアウトを作る

概要

以下の様なショーケースレイアウトを作る。
上に表示されている画像をViewPagerで実装して、スライドできるようにする。

f:id:tiro105:20140622184309p:plain

詳細

listViewのHeaderにindicatorとViewPagerを組み合わせたshowCaseを設定する。
設定するmainFragment

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // リストのヘッダーにショーケースを追加
        int height = (int) (240 * getResources().getDisplayMetrics().density);
        mShowcase = new Showcase(getActivity());
        mShowcase.setLayoutParams(new AbsListView.LayoutParams(
                LayoutParams.MATCH_PARENT, height));

        ListView listView = getListView();
        listView.addHeaderView(mShowcase, null, false);
    }

     @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // ショーケースをセットアップ
        mShowcase.setImageResources(sImages);

        // リストをセットアップ
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, sTitles));
    }

showCaseに設定するIndicatorを作成する。

public class ViewPagerIndicator extends RadioGroup {

    // indicatorの数
    private int mCount;

RadioButtonのPaddingをVersionごとの違いを気をつけつつ、ページ数とpositonの設定。

    /**
     * ページ数をセットする
     * 
     * @param count
     */
    public void setCount(int count) {
        mCount = count;
        removeAllViews();
        // 指定されたページ数分だけRadioButtonを追加
        for (int i = 0; i < count; i++) {
            // RadioButtonにインディケータの画像をセット
            RadioButton rb = new RadioButton(getContext());
            rb.setFocusable(false);
            rb.setClickable(false);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                // 4.2以前は背景画像でpaddingを設定していたため、RadioButtonのサイズを画像サイズセットしなければならない
                Drawable d = getResources().getDrawable(R.drawable.indicator);
                rb.setButtonDrawable(d);
                LinearLayout.LayoutParams params = generateDefaultLayoutParams();
                params.width = d.getIntrinsicWidth();
                params.height = d.getIntrinsicHeight();
                rb.setLayoutParams(params);
            } else {
                rb.setButtonDrawable(R.drawable.indicator);
            }
            addView(rb);
        }
        setCurrentPosition(-1);
    }

    /**
     * 現在の位置をセットする
     * 
     * @param position
     */
    public void setCurrentPosition(int position) {
        if (position >= mCount) {
            position = mCount - 1;
        }
        if (position < 0) {
            position = mCount > 0 ? 0 : -1;
        }

        if (position >= 0 && position < mCount) {
            // 現在の位置のRadioButtonをチェック状態にする
            RadioButton rb = (RadioButton) getChildAt(position);
            rb.setChecked(true);
        }
    }


設定するshowCaseを実装する。
FrameLayoutを継承し、ViewPagerとIndicatorを持つ

public class Showcase extends FrameLayout {

    ViewPager mViewPager;
    ViewPagerIndicator mViewPagerIndicator;

画像リソースの設定メソッドを作り、Indicatorと紐付ける。

    public void setImageResources(int[] resIds) {
        // 画像のリソースIDの配列からアダプターを作成
        CustomPagerAdapter adapter = new CustomPagerAdapter(getContext(), resIds);
        mViewPager.setAdapter(adapter);

        // インディケータと紐付け
        mViewPager
                .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        mViewPagerIndicator.setCurrentPosition(position);
                    }

                });

        mViewPagerIndicator.setCount(adapter.getCount());
    }		

showCase用のAdapterを作成

    // ショーケース用のアダプター
    static class CustomPagerAdapter extends PagerAdapter {

        Context mContext;
        int[] mResIds;

        …

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            // ViewPagerの1ページ部分はImageViewのみ
            ImageView iv = new ImageView(mContext);
            iv.setImageResource(mResIds[position]);
            iv.setScaleType(ScaleType.CENTER_CROP);
            container.addView(iv);
            return iv;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            View v = (View) object;
            container.removeView(v);
        }
    }

参考

Android Pattern Cookbook マーケットで埋もれないための差別化戦略

Android Pattern Cookbook マーケットで埋もれないための差別化戦略