この質問は非常に興味深いトピックです。そして、ある程度のカスタマイズを行う準備をしてください。
まず、HorizonalScrollView をドロップします。役に立たないと思います。各項目のレイアウトは次のようになります (疑似コード、XML を自分で作成できます =] ):
FrameLayout
RelativeLayout id:topContent background:someSolidColor
// inside this RelativeLayout, the stuff that is visible on the ListView
RelativeLayout id:bottomContent
// inside this RelativeLayout, the stuff that is behind the content
/FrameLayout
そうすれば、文字通り、あるものを他のものの上に置くことができます。また、topContent には単色の背景があることに注意してください。背景を指定しない場合、両方の RelativeLayout が表示されます。また、私が RelativeLayout を使用したのは、それらが好きであり、柔軟性が気に入っているからです。ただし、これは、リスト ビューの内容と設定によって異なります。
そして今が楽しい時です。GestureDetector で指のスライドを検出する必要があり、その値を使用して にマージン オフセットを生成しますid:topContent
。
次のように TouchListener を作成できます。
public class MySlideListener extends View.OnTouchListener{
private View v;
private GestureDetector gestureDetector;
public MySlideListener (View v){
this.v = v;
gestureDetector = new GestureDetector(v.getContext(), myGestureListener);
}
public boolean onTouch (View v, MotionEvent event){
return gestureDetector.onTouchEvent(event);
}
private SimpleOnGestureListener myGestureListener = new SimpleOnGestureListener(){
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
// now here we make the view scroll
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
lp.leftMargin = distanceX;
lp.rightMargin = -distanceX;
// You might need to call view.requestLayout();
// but first give it a try without it
// This part of the method for processing the horizontal
// offset can (and should) be further developed to add some
// 'snap-in' or transparency functionality to make the whole
// concept work better.
// But this code should give you a proof of concept on how to deal with stuff.
// The important part is that now you have a call back that have access
// to the view during onScroll.
// Also might be necessary to enable/disable the bottomContent view
// in order for it to be not clickable whilst not visible.
return true;
}
}
}
次に、 ListView ごとtopContent
に(おそらくアダプターからの getView 内に)新しいリスナーを設定しますtopContentView.setOnTouchListener(new MySlideListener(topContentView));
このコードはすべて暗記したものであり、100% テストされていないことを覚えておいてください。
編集:
上記のコードは正しい方向ですが、100% テストされていません。以下のコードは、コンパイルしてテストしたところです。このコードは機能します。
このクラスは、アダプターで作成されたすべてのアイテムに 1 つだけ作成して同じインスタンスを適用できるため、少し効率的です。タッチ イベントでスクロールするビューを取得していることがわかります。
public class MySlideListener implements View.OnTouchListener {
private View view;
private ListView listView;
private GestureDetector gestureDetector;
public MySlideListener(ListView lv) {
listView = lv;
gestureDetector = new GestureDetector(lv.getContext(), myGestureListener);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
view = v;
gestureDetector.onTouchEvent(event);
return true;
}
private SimpleOnGestureListener myGestureListener = new SimpleOnGestureListener() {
private int origLeft, origRight;
public boolean onDown(MotionEvent e) {
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
origLeft = lp.leftMargin;
origRight = lp.rightMargin;
return true;
};
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
listView.requestDisallowInterceptTouchEvent(true);
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
lp.leftMargin = (int) (origLeft + (e2.getRawX() - e1.getRawX()));
lp.rightMargin = (int) (origRight - (e2.getRawX() - e1.getRawX()));
view.requestLayout();
return true;
};
};
}