ここでの大雑把な仕様は、
・最初のページは全ページの真ん中のページ(例えば全5ページなら3ページが初期位置)
・背景画像は必ず横長の画像
・背景は横にしか移動しない
ということにします。
ちなみに私はAndroidに関しては素人なので、この実装よりもいいやり方があれば是非是非教えて頂きたい。
というか、こんな実装を必要とする人っているのか??
それでは、とりあえず実装後のMainActivityはこんな感じとなります。
public class MainActivity extends Activity { private CustomAdapter adapter; private ViewPager mViewPager; private ImageView mImageView; private Bitmap mBitmap; private float displayW; private float displayH; // -----追記 private Matrix matrix; private float currentBmpX; private int maxMoveBmpX; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // カスタム PagerAdapter を生成 adapter = new CustomAdapter(this); adapter.add(Color.RED); adapter.add(Color.GREEN); adapter.add(Color.BLUE); adapter.add(Color.BLACK); adapter.add(Color.WHITE); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); displayW = metrics.widthPixels; displayH = metrics.heightPixels; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 画像そのものは読み込まない BitmapFactory.decodeResource(getResources(), R.drawable.wall, options); // dpi計算 int bmpNativeHeight = options.outHeight; float dpiRatio = bmpNativeHeight / displayH; float calcDpi = metrics.densityDpi * dpiRatio; if (mBitmap == null || mBitmap.isRecycled()) { options.inJustDecodeBounds = false; options.inDensity = (int) calcDpi; mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.wall, options); } mImageView = new ImageView(this); mImageView.setImageBitmap(mBitmap); mImageView.setScaleType(ScaleType.MATRIX); addContentView(mImageView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // ViewPager を生成 mViewPager = new ViewPager(this); mViewPager.setAdapter(adapter); // -----追記 matrix = new Matrix(); currentBmpX = (mBitmap.getScaledWidth(metrics) / 2) - (displayW / 2); maxMoveBmpX = (int) (mBitmap.getScaledWidth(metrics) - displayW); mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { private int currentPage; @Override public void onPageSelected(int pageNumber) { currentPage = pageNumber; currentBmpX = getAbsPositionX(pageNumber); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffsetPixels == 0) { return; } //page移動中の処理 float scaledOffsetPixels = positionOffsetPixels * getScaleValue(); // ページ毎の始点のx座標 float absolutePosition = getAbsPositionX(position); currentBmpX = absolutePosition + scaledOffsetPixels; mImageView.setImageMatrix(getMatrix(matrix, -currentBmpX)); mImageView.invalidate(); } @Override public void onPageScrollStateChanged(int state) { } protected float getAbsPositionX(int page) { return (maxMoveBmpX / (adapter.getCount() - 1)) * page; } }); addContentView(mViewPager, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } @Override protected void onResume() { super.onResume(); mViewPager.setCurrentItem((adapter.getCount()/2), true); mImageView.setImageMatrix(getMatrix(matrix, -currentBmpX)); } protected Matrix getMatrix(Matrix matrix, float xPosition) { if (xPosition > 0) { xPosition = 0; } if (Math.abs(xPosition) > maxMoveBmpX) { xPosition = -maxMoveBmpX; } matrix.setTranslate(xPosition, 0); return matrix; } public float getScaleValue() { float displayWidth = getWindowManager().getDefaultDisplay().getWidth(); float fullScreenSize = displayWidth * (adapter.getCount()-1); return maxMoveBmpX / fullScreenSize; } }
前回と比較して、onCreate()で今回追加実装した箇所には「// -----追記」とコメントしています。
上の行番号で言うと、
11〜14行目
59〜96行目
その他のメソッドは今回追加実装してます。
まぁ、これだけで読む気も失せてくるんですが、説明を(今後の自分の為にも)。
まず、61行目と62行目の
currentBmpX = (mBitmap.getScaledWidth(metrics) / 2) - (displayW / 2); maxMoveBmpX = (int) (mBitmap.getScaledWidth(metrics) - displayW);ですが、
currentBmpXは、画像の左上を原点としたときの、現在画面に表示されている背景画像の左上のX座標です。
これの初期位置(つまり、中央のページで表示される背景画像の左上のX座標)を計算しています。
分かりにくいけど、計算で出しているのは上の画像の赤い点の位置ですね。
次に、maxMoveBmpXですが、これは最後のページで表示される背景画像のX座標の位置となります。
まぁ、このへんは特にポイントでも何でもないです。
今回のポイントとなる実装はViewPagerのsetOnPageChangeListenerですね。
上記コードの63行目〜96行目の部分です。
このListnerはページが動いているときにその状態を通知しまくってくれるので、その情報を使って背景画像の位置をImageView.setImageMatrixでズラしていくって感じですね。
OnPageChangeListenerでのポイントといえばポイントなんですが、
ページが進むと背景画像がマイナス方向(左方向)に移動する点。
何か、感覚的に理解しにくいのは私だけ??
それ以外は特にポイントってものは無いですね。実装も大したことしてないし。
あとポイントじゃないけど74行目〜76行目のif文。
別にこれなくても普通に動くんですけど、ページ移動中にそのときの移動距離が引数で渡ってくるんですが(positionOffsetPixels)、ページ移動が完了してからも何故かしばらく0が渡ってくるので、余計な処理を省く為に入れてます。
まぁ、なんとなくです。いらない気がしますね。。。。
長々と書きましたが、これでそれなりの動きになるはずです。
備忘録ついでに誰かのお役に立てれば幸いかと。
あ、変数名やメソッド名はあまり突っ込まないでね。
0 件のコメント:
コメントを投稿