java - 当具有 2 层时,FrameLayout 无法正确处理触摸请求

标签 java android user-interface callback drag

我正在尝试扩展 FrameLayout 以便能够决定哪个 View 传递触摸事件:

myApp 是这样的: enter image description here

这些点是水平 ScrollView ,矩形只是一个 View 。 当您触摸点区域时,它就会滚动。我希望矩形可以拖动。 我可以一次做一个(我的意思是 - 如果框架只有一个 child )。但不是两者兼而有之。 我想我需要重写:onInterceptTouchEvent,但没有设法将事件传递给矩形 View 。这是我的代码: Activity_main.xml:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/LinearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <com.example.trashproject.FrameWithTouchControl
            android:id="@+id/frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <View
                android:id="@+id/selector"
                android:layout_width="45dp"
                android:layout_height="match_parent"
                android:background="#33FF0000" >
            </View>

             <HorizontalScrollView
            android:id="@+id/horizontalScroll"
            android:layout_width="wrap_content"
            android:layout_height="match_parent" >

            <TableLayout
                android:id="@+id/table"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="horizontal" >
            </TableLayout>
        </HorizontalScrollView>

        </com.example.trashproject.FrameWithTouchControl>
    </LinearLayout>

FrameWithTouchControl.java:

package com.example.trashproject;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;

public class FrameWithTouchControl extends FrameLayout {

    private static final String TAG ="FrameWithTouchControl" ;
    private float curSelectorPositionX1;
    private float curSelectorPositionX2;
    private boolean isDragging = false;
    private View mSelector;
    private int mTouchSlop;

    public FrameWithTouchControl(Context context) {
        super(context);
        init();

    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        initViewMembers();
    }


    public FrameWithTouchControl(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    public FrameWithTouchControl(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        init();
    }


    private void initViewMembers() {
        mSelector = this.findViewById(R.id.selector);

    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        // Always handle the case of the touch gesture being complete.
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            // Release the scroll.
            isDragging = false;
            return false; // Do not intercept touch event, let the child handle it
        }
        curSelectorPositionX1 = mSelector.getLeft();
        curSelectorPositionX2 = mSelector.getRight();
        float evX = ev.getX();
        //if the touch is out of the selector's area
        if (evX >= curSelectorPositionX2 || evX <= curSelectorPositionX1) {
            return false;
        }

        switch (action) {
        case MotionEvent.ACTION_MOVE:
            if (isDragging) {
                // We're currently dragging, so yes, intercept the 
                // touch event!
                mSelector.onTouchEvent(ev);
                return true;
            }

            mSelector.onTouchEvent(ev);
            return true;



        }//switch
        return false;
    }//onIntercept
}

MainActivity.java:

package com.example.trashproject;

import java.util.Calendar;
import java.util.Random;

import android.content.ClipData;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;
public class MainActivity extends FragmentActivity{


    private static final int ROWS =8;
    private static final int COLS = 100;
    private static final String TAG = "MainActivity";
    private TableLayout mTable;
    private TextView[][] mCircles;
    private boolean[][] mData;
    private LayoutInflater mInflater;
    private FrameLayout mFrame;
    private View mSelector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mData = generateFakeGuestsTimes();
        mInflater =(LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        makeTable();
        mFrame = (FrameLayout) findViewById(R.id.frame);

        mSelector = findViewById(R.id.selector);
        mSelector.setOnTouchListener(new OnTouchListener() {

            boolean isDragging;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.d(TAG, "selector touch triggered" );
                Log.d(TAG, event.toString());
                int action = event.getAction();
                float deltaX = 0;
                if (action==MotionEvent.ACTION_DOWN && !isDragging) {
                    isDragging = true;
                    deltaX = event.getX();
                    return true;
                } else if (isDragging) {
                    if (action== MotionEvent.ACTION_MOVE) {
                        v.setX(v.getX() + event.getX() - deltaX);
                    } else if (action == MotionEvent.ACTION_CANCEL) {
                        isDragging = false;
                        return true;
                    } else if (action == MotionEvent.ACTION_UP) {
                        isDragging = false;
                        return false;
                    }
                }
                return false;
            }
        });


    }
/**** NOT RELEVANT FROM HERE *******/
    private boolean[][] generateFakeGuestsTimes() {
        boolean[][] values = new boolean[ROWS][COLS];
        Random rand = new Random();
        for (int i = 0; i < ROWS; i++) {
            for (int j = 0; j < COLS    ; j++) {
                values[i][j] = rand.nextBoolean();
            }
        }
        return values;

    }
    public void onClick(View view) {
        Log.d(TAG, "numOfChildren" + mTable.getChildCount());
    }


    private void makeTable() {
        mTable = (TableLayout) findViewById(R.id.table);

        TableRow.LayoutParams rowParams = new TableRow.LayoutParams();
        rowParams.width = LayoutParams.WRAP_CONTENT;
        rowParams.height = 67;
        mCircles = new TextView[ROWS][COLS];
        final TableRow[] row = new TableRow[ROWS];
        final TextView[] headerText = new TextView[ROWS];
        long start = cal.getTimeInMillis();
        for (int i = 0; i < ROWS; i++) {
            row[i] = new TableRow(this);
            row[i].setLayoutParams(rowParams);
            for (int j = 0; j < COLS; j++) {
                mCircles[i][j] = (TextView) mInflater.inflate(R.layout.calendar_month_grid, null);
                if (mData[i][j]) {
                    mCircles[i][j].setBackgroundResource(R.drawable.small_circle);
                } else {                    
                    mCircles[i][j].setBackgroundResource(R.drawable.small_circle_red);
                }
                row[i].addView(mCircles[i][j]);
            }
            mTable.addView(row[i]);
        }//outer loop

        long end = cal.getTimeInMillis();
        Log.d(TAG, "time of operation=" + end + ", " + start + ", " + String.valueOf(end - start));
    }

最佳答案

我通过切换 FrameLayout 内的顺序解决了该问题。 显然,框架布局以相反的顺序设置图层。即:

<FrameLAyout>
   <View1/>
   <View2/>
</FrameLAyout>

View2 将位于上层。 View2将首先获取触摸回调,如果它不处理触摸,View1将获取调用。 IE。这和绘画是一样的。底层是View1,上层是View2。有道理

关于java - 当具有 2 层时,FrameLayout 无法正确处理触摸请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27950243/

相关文章:

java - 将 byte[] 转换为 ArrayList<String>

java - 散点二维数据的线性插值

android - 将图像共享到其他应用程序

c++ - GUI 和文本模式 C++ 设计以消除冗余(可选参数?函数重载?)

javascript - Golang 程序的 Electron 用户界面?

java - 从字节码中抓取java类名的函数

java - 无法通过源启动 JIRA

android - 如何在 API 22 中获取正在运行的应用程序列表

java - 错误: cannot find symbol class FirebaseInstanceIdService

java - awt eventqueue 0 空指针异常错误