どういうわけか理解できないかなり単純な質問があります。独自のビュー (onDrawn はオーバーライドされます) と LinearLayout を拡張する別の透明なビューを持つ FrameLayout を使用しています。透明なビューにスクロールを追加したいのですが、XML で ScrollView を使用すると Classcast 例外がスローされます。
私の代替手段は、独自にスクロールを実装することでした (たとえば、LinearLayout の scrollTo を使用して、そのメソッドを使用した例を見つけることができません) が、OnGestureListener は onScroll をトリガーしませんが、onShowPress と onLongPress はトリガーされます。次に、LinearLayout で onTouchEvent を使用しようとしましたが、ACTION_MOVE ではなく ACTION_DOWN のみを認識します。私自身の見解では、すべてが完璧に機能します。
ここで XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/home_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.unimelb.pt2.ui.WaterfallView
android:id="@+id/waterfall_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="0DUEIIn35xtmfWC2DXprK5kqNF-aEaNgRJ4ONxw"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="bottom"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingRight="0px">
<com.unimelb.pt2.ui.TransparentPanel
android:id="@+id/workbench"
android:layout_width="fill_parent"
android:layout_height="10px"
android:paddingTop="0px"
android:paddingLeft="0px"
android:paddingBottom="0px"
android:paddingRight="0px">
</com.unimelb.pt2.ui.TransparentPanel>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:gravity="right"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingRight="0px">
<com.unimelb.pt2.ui.TransparentPanel
android:id="@+id/tagarea"
android:layout_width="50px"
android:layout_height="fill_parent"
android:paddingTop="0px"
android:paddingLeft="0px"
android:paddingBottom="0px"
android:paddingRight="0px">
</com.unimelb.pt2.ui.TransparentPanel>
</LinearLayout>
</FrameLayout>
WaterfallView の基本的な構成は次のとおりです。
public class WaterfallView extends View {
private GestureDetector gestureScanner;
private Vector<PictureEntry> allPictures = new Vector<PictureEntry>();
public WaterfallView(Context context) {
super(context);
this.initialize(context);
}
public void initialize(Context context) {
this.setFocusable(true);
this.setClickable(true);
this.context = context;
allPictures.add(new PictureEntry(context, R.drawable.sample_0));
allPictures.add(new PictureEntry(context, R.drawable.sample_1));
allPictures.add(new PictureEntry(context, R.drawable.sample_2));
allPictures.add(new PictureEntry(context, R.drawable.sample_3));
allPictures.add(new PictureEntry(context, R.drawable.sample_4));
allPictures.add(new PictureEntry(context, R.drawable.sample_5));
allPictures.add(new PictureEntry(context, R.drawable.sample_6));
allPictures.add(new PictureEntry(context, R.drawable.sample_7));
}
public void setGestureDetector(GlassPane gp) {
gestureScanner = new GestureDetector(context, gp);
}
@Override
protected void onDraw(Canvas canvas) {
Iterator<PictureEntry> iter = allPictures.iterator();
int i = 0;
while (iter.hasNext()) {
PictureEntry pic = iter.next();
pic.draw(canvas)
}
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureScanner.onTouchEvent(event)) {
return Prototype.glass.pictureTouch(event);
} else return false;
}
}
GlassPane の基本的な構造は次のとおりです。
public class GlassPane implements OnGestureListener {
public GlassPane(WaterfallView waterfall) {
super();
waterfall.setGestureDetector(this);
}
public boolean pictureTouch(MotionEvent event) {
// Handles drag and drop and zoom pinch
}
public boolean onDown(MotionEvent e) {
Log.i("Test", "DOWN");
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.i("Test", "FLING");
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Log.i("Test", "LONG PRESS");
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
Log.i("Test", "SCROLL");
return true;
}
@Override
public void onShowPress(MotionEvent e) {
Log.i("Test", "SHOW PRESS");
}
}
ここでは、TransparentPanel の構成を示します。
public class TransparentPanel extends LinearLayout {
private Paint innerPaint, borderPaint;
private int width, height, scrollOffset;
private Context mContext;
public TransparentPanel(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
public TransparentPanel(Context context) {
super(context);
init();
}
private void init() {
innerPaint = new Paint();
innerPaint.setARGB(225, 75, 75, 75); // gray
innerPaint.setAntiAlias(true);
}
public void setDimension(int w, int h) {
width = w; height = h;
this.setLayoutParams(new LayoutParams(width, height));
this.invalidate();
}
@Override
protected void dispatchDraw(Canvas canvas) {
RectF drawRect = new RectF();
drawRect.set(0, 0, width, height);
canvas.drawRect(drawRect, innerPaint);
super.dispatchDraw(canvas);
}
private void measure() {
if(this.getOrientation()==LinearLayout.VERTICAL) {
int h = 0;
for(int i=0; i<this.getChildCount(); i++) {
View v = this.getChildAt(i);
h += v.getMeasuredHeight();
}
height = (h < height) ? height : h;
Log.d(Prototype.TAG, "mW:"+width+", mH:"+height);
}
this.setMeasuredDimension(width, height);
}
}