スクローラーは苦しんだ。今もよく分からない。とりあえず、動く。
スクロールは、スクロール範囲を考える事。
スクリーンサイズが、200x100。
画像が400x200。だったとすると、
画像の(0,0)から(200,100)まで。x= 0~200、y= 0~100。
このx、yの組み合わせで元画像がピッタリとスクリーン上をスクロールできる。
スクリーン
sW = 200
sH = 100
画像
iW = 400
iH = 200
scrollMax
sMaxX = iW - sW
sMaxY = iH - sH
0 <= scrX <= sMaxX
0 <= scrY <= sMaxY
スライドの移動量を計算してスクロール。
画像が小さかったら、scrollMaxは負になる。
その時はスクロールさせない。
onScroll()は、その制限でスクロールさせる。
imageView に padding 設定をするとスクロールオフセットは切り離せる。
scrW=200/ imageW=100 の時、view.setPadding( 50, paddingY, 50, paddingY);
と設定すると、view.scrollTo( 0, y );は画面中央、両端空白あり。
view.setPadding( 0, 0, 0, 0 );(未設定状態のつもり)だと
view.scrollTo( 0, y );は画面左端寄り、右側空白あり。
状況により使い分け。
スクロール前提なら画像をセットした時に padding も設定かな。
面倒なのがフリンク。
デベロッパーのリファレンスが分からん。文献も分からん。
思いつくことを試して結果データを分析して多分?こうかな?
・スクローラーとアニメーターを定義。
・アニメーターを実行。(別スレッドで動いているみたい)
・アニメーター内でスクローラーに計算させて、値を取り出し、view.scrollTo( x, y )にセット。
・スクローラーが完了したら、アニメーターを止める。
みたいな。
mScroller.fling(
startX,
startY,
velocityX,
velocityY,
minX, maxX,
minY, maxY,
overX,overY
);
【startX, startY】
タップ位置だと思うよね~。これをDown位置と捉えた時はスクロール値に変換をしないといけない。
最初からスクロールオフセットだと決めれば、後の min、max はスクロールの制限範囲になる。計算もすこぶる楽。
ただし、制限が付く。フルスクリーンフルスクロールのみの設定。
複数のコンテンツが合わさって複数の領域でスクロールさせる場合は使えない。と思う。注意!
自分はフルスクリーンフルスクロールだから楽にいく。Padding設定は必須。
検索での説明は指定領域内の狭い範囲のスクロールばかりだったので、理解に苦しんだ。orz...
別問題も残っている。OverScroll の overX,overY の設定は、画像外にスクロールが飛び出して、正常な位置に戻るという飛び出し距離。
試したが時々、完全に戻らない。調べると本来スクローラーが完了してアニメーターが終了するはずが、スクローラーが完了の信号を受け取らずにアニメーターがうやむやにしている事が時々ある。
謎だ?別ルートで何か動いている…。なのでオーバー仕様は封印。
public class MainActivity extends AppCompatActivity {
private GestureDetectorCompat mDetector;
private OverScroller mScroller;
private ValueAnimator scrollAnimator = ValueAnimator.ofFloat(0,1);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetector = new GestureDetectorCompat(this, new MyGestureListener() );
mScroller = new OverScroller( this,null );
scrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) { // アニメーター実行で呼ばれる
if ( !mScroller.isFinished() ) {
mScroller.computeScrollOffset(); // 計算
mImageSwitcher.getCurrentView().scrollTo( mScroller.getCurrX(), mScroller.getCurrY() ); // スクロール実行
} else
scrollAnimator.cancel();
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if ( mDetector.onTouchEvent(event) ) return true;
return super.onTouchEvent(event);
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
@ Override
public boolean onDown(MotionEvent event) {
if ( !mScroller.isFinished() ) mScroller.abortAnimation();
scrollAnimator.cancel();
return false;
}
@Override
public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) {
scrollImage( (ImageView)mImageSwitcher.getCurrentView(), distanceX, distanceY );
return true;
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
ImageView view = (ImageView)mImageSwitcher.getCurrentView();
int w = view.getDrawable().getIntrinsicWidth();
int h = view.getDrawable().getIntrinsicHeight();
int startX = view.getScrollX();
int startY = view.getScrollY();
mScroller.fling(
startX,
startY,
(int) -velocityX,
(int) -velocityY,
0, Math.max(0,w-getScreenWidth()),
0, Math.max(0,h-getScreenHeight())
);
scrollAnimator.start(); // 実行
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
loadImage((int)event.getY());
return true;
}
};
public void scrollImage ( ImageView view, float x, float y ) {
int cX = (int) x;
int cY = (int) y;
int scrX = view.getScrollX();
int scrY = view.getScrollY();
int dx = ( view.getDrawable().getIntrinsicWidth() - getScreenWidth() );
int dy = ( view.getDrawable().getIntrinsicHeight() - getScreenHeight() );
if ( dx > 0 ) {
if ( x > 0 ) {
if ( scrX == dx ) cX = 0;
else {
int xx = dx - scrX;
if ( x >= xx ) cX = xx;
}
} else if ( x < 0 ){
if ( scrX == 0 ) cX = 0;
else if ( scrX > 0 && -scrX >= x ) cX = -scrX;
} else cX = 0;
} else
cX = 0;
if ( dy > 0 ) {
if ( y > 0 ) {
if ( scrY == dy ) cY = 0;
else {
int yy = dy - scrY;
if ( y >= yy ) cY = yy;
}
} else if ( y < 0 ){
if ( scrY == 0 ) cY = 0;
else if ( scrY > 0 && -scrY >= y ) cY = -scrY;
} else cY = 0;
} else
cY = 0;
view.scrollBy( cX, cY );
}
}