I'm trying to extend FrameLayout to be capable to decide for which view to pass the touch event:
myApp is like this:
The dots are in horizontal scrollview, and the rectangle is just a view. When you touch the dots area it's scrolls. I would like the rectangle to be draggable. I can do that one at a time(I mean - if the frame has only one child). but not both. I've figured I need to override: onInterceptTouchEvent but didn't manage to pass the event to the rectange View. here is my code: 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));
}
I resolved the issue by switching the order inside the FrameLayout. apparently the framelayout set the layers in opposite order. ie:
<FrameLAyout>
<View1/>
<View2/>
</FrameLAyout>
View2 will be on the upper layer. View2 will first gets the touch callbacks, if it is not handling the touch, View1 will get a call. Ie It is the same as drawing. the bottom layer is View1, the upper is View2. make sense
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.