与滚动的问题的LinearLayout [英] Problems with Scrolling in LinearLayout

查看:117
本文介绍了与滚动的问题的LinearLayout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当简单的问题,这在某种程度上我想不通。我使用的是与自己的观点一的FrameLayout(onDrawn被重写),并延伸的LinearLayout另一透明视图。我想补充的滚动透明的观点,但如果我在XML使用滚动型中Classcast异常。

我的选择是实现(在LinearLayout中,在那里我无法找到使用该方法的例子与scrollTo如)滚动我自己,但OnGestureListener不onScroll触发,而昂秀preSS和onLong preSS被触发。然后,我尝试在的LinearLayout使用onTouchEvent,但是它只能识别ACTION_DOWN,不ACTION_MOVE。我个人认为所有的作品完美。

下面的XML:

 <的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
        机器人:ID =@ + ID / home_container
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =FILL_PARENT>< com.unimelb.pt2.ui.WaterfallView
        机器人:ID =@ + ID / waterfall_view
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =FILL_PARENT
        机器人:apiKey =0DUEIIn35xtmfWC2DXprK5kqNF-aEaNgRJ4ONxw/>< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
                机器人:layout_width =FILL_PARENT
                机器人:layout_height =FILL_PARENT
                机器人:方向=垂直
                机器人:重力=底                机器人:paddingLeft =0像素
                机器人:paddingTop =0像素
                机器人:paddingRight =0像素>    < com.unimelb.pt2.ui.TransparentPanel
            机器人:ID =@ + ID /工作台
            机器人:layout_width =FILL_PARENT
            机器人:layout_height =10px的
            机器人:paddingTop =0像素
            机器人:paddingLeft =0像素
            机器人:paddingBottom会=0像素
            机器人:paddingRight =0像素>
    < /com.unimelb.pt2.ui.TransparentPanel>< / LinearLayout中>< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
                机器人:layout_width =FILL_PARENT
                机器人:layout_height =FILL_PARENT
                机器人:方向=横向
                机器人:重力=右                机器人:paddingLeft =0像素
                机器人:paddingTop =0像素
                机器人:paddingRight =0像素>    < com.unimelb.pt2.ui.TransparentPanel
                机器人:ID =@ + ID / tagarea
                机器人:layout_width =50像素
                机器人:layout_height =FILL_PARENT
                机器人:paddingTop =0像素
                机器人:paddingLeft =0像素
                机器人:paddingBottom会=0像素
                机器人:paddingRight =0像素>
    < /com.unimelb.pt2.ui.TransparentPanel>< / LinearLayout中>< /&的FrameLayout GT;

下面的WaterfallView的基本结构:

 公共类WaterfallView扩展视图{
私人GestureDetector gestureScanner;
私人矢量<&PictureEntry GT; allPictures =新的矢量<&PictureEntry GT;();
公共WaterfallView(上下文的背景下){
    超级(上下文);
    this.initialize(上下文);
}公共无效初始化(上下文的背景下){
    this.setFocusable(真);
    this.setClickable(真);
    this.context =背景;    allPictures.add(新PictureEntry(上下文,R.drawable.sample_0));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_1));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_2));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_3));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_4));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_5));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_6));
    allPictures.add(新PictureEntry(上下文,R.drawable.sample_7));
}公共无效setGestureDetector(玻璃面板GP){
    gestureScanner =新GestureDetector(背景下,GP);
}
@覆盖
保护无效的onDraw(帆布油画){
    迭代器< PictureEntry> ITER = allPictures.iterator();
    INT I = 0;
    而(iter.hasNext()){
        PictureEntry PIC = iter.next();
        pic.draw(画布)
    }
    无效();
}@覆盖
公共布尔onTouchEvent(MotionEvent事件){
    如果(gestureScanner.onTouchEvent(事件)){
        返回Prototype.glass.pictureTouch(事件);
    }否则返回false;
}
}

下面的玻璃面板的基本结构:

 公共类玻璃面板实现OnGestureListener {
公共玻璃面板(WaterfallView瀑布){
    超();
    waterfall.setGestureDetector(本);
}公共布尔pictureTouch(MotionEvent事件){
    //把手拖拽和缩放捏
}
公共布尔onDown(MotionEvent五){
    Log.i(测试,DOWN);
    返回false;
}公共布尔onFling(MotionEvent E1,E2 MotionEvent,浮velocityX,
        浮动velocityY){
    Log.i(测试,抛球);
    返回false;
}@覆盖
公共无效onLong preSS(MotionEvent五){
    Log.i(测试,LONG $ P $干燥综合征);
}@覆盖
公共布尔onScroll(MotionEvent E1,E2 MotionEvent,浮distanceX,
        浮动distanceY){
    Log.i(测试,滚动);
    返回true;
}@覆盖
公共无效昂秀preSS(MotionEvent五){
    Log.i(测试,SHOW $ P $干燥综合征);
}}

和这里的TransparentPanel的结构:

 公共类TransparentPanel扩展的LinearLayout {
私人油漆innerPaint,borderPaint;
私人诠释宽度,高度,scrollOffset;
私人语境mContext;公共TransparentPanel(上下文的背景下,ATTRS的AttributeSet){
    超(背景下,ATTRS);
    mContext =背景;
    在里面();
}公共TransparentPanel(上下文的背景下){
    超级(上下文);
    在里面();
}私人无效的init(){
    innerPaint =新的油漆();
    innerPaint.setARGB(225,75,75,75); // 灰色
    innerPaint.setAntiAlias​​(真);
}公共无效setDimension(INT W,INT高){
    宽度= W;高度= H;
    this.setLayoutParams(新的LayoutParams(宽度,高度));
    this.invalidate();
}@覆盖
保护无效dispatchDraw(帆布油画){
    RectF的drawRect =新RectF();
    drawRect.set(0,0,宽度,高度);
    canvas.drawRect(drawRect的,innerPaint);
    super.dispatchDraw(画布);
}私人无效措施(){
    如果(this.getOrientation()== LinearLayout.VERTICAL){
        INT H = 0;
        的for(int i = 0; I< this.getChildCount();我++){
            视图V = this.getChildAt(I)
            H + = v.getMeasuredHeight();
        }
        身高=(H<高度)?高度:H;
        Log.d(Prototype.TAG,MW:+宽+,MH:+高);
    }
    this.setMeasuredDimension(宽度,高度);
}}


解决方案

好吧,我想我终于想通了一切:


  1. 该ClassCastException异常是因为在我TransparentPanel我尝试分配的LayoutParams到面板上没有说明哪一种的LayoutParams的抛出。我认为这应该是LinearLayout.LayoutParams但实际上我需要分配的ViewGroup,其中我把观的LayoutParams,即在RelativeLayout的我的情况。


  2. 我GlassPanel被放置在的FrameLayout的底部而不是在顶部更好。该MotionEvents要比从上向下传递到下预期。我刚开始无论是躺在上面,如果事件不是由层处理的我返回false和向下传递事件到下一层,而不是在顶部有一个真正的玻璃面板。


  3. 为了处理上的FrameLayout我只需要覆盖onTouchEvent方法,所有使用玻璃面板作为事件监听视图的顶部的玻璃面板的事件。就在WaterfallView喜欢在上面code。但仔细MotionEvent.getX()和MotionEvent.getY()的返回值相对于观不是绝对的。解决方案(2)完美的作品相对于玻璃面板。


I have a fairly simple question which somehow I can't figure out. I'm using a FrameLayout with an own view (onDrawn is overriden) and another transparent view which extends LinearLayout. I want to add scrolling for the transparent view, but if I use ScrollView in the XML a Classcast exception is thrown.

My alternative was to implement scrolling on my own (e.g. with scrollTo in LinearLayout, where I can't find any example using that method), but the OnGestureListener doesn't trigger onScroll, while onShowPress and onLongPress are triggered. I then tried to use onTouchEvent in the LinearLayout, but it only recognises ACTION_DOWN, not ACTION_MOVE. In my own view all that works perfectly.

Here the 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>

Here the basic construct of the 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;
}
}

Here the basic construct of the 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");
}

}

And here the construct of the 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); 
}

}

解决方案

Okay, I think I finally figured everything out:

  1. The ClassCastException was thrown because in my TransparentPanel I try to assign LayoutParams to the panel without stating which kind of LayoutParams. I thought it should be LinearLayout.LayoutParams but in fact I need to assign the LayoutParams of the ViewGroup in which I place the View, i.e. RelativeLayout in my case.

  2. My GlassPanel is placed better on the bottom of the FrameLayout rather than on the top. The MotionEvents are than passed down from top to bottom as expected. I just start with whatever is lying on top and if the event is not handled by that layer I return false and pass down the event to the next layer rather than having a real GlassPane on top.

  3. In order to handle the event in the GlassPane on top of the FrameLayout I just need to override the onTouchEvent method in all the Views that use the GlassPane as EventListener. Just like in WaterfallView in the above code. But careful MotionEvent.getX() and MotionEvent.getY() return values relative to that View and not absolute. Solution (2) works perfect relatively to the GlassPane.

这篇关于与滚动的问题的LinearLayout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆