I want to implement single figure rotation and scalling functinality on Frame Layout using bottom right cornor button of Framlayout.following is my code that not working fine.I am triying more than 15 days for it but not find the solution for layout rotation.there are lots of demo available for image rotatin.but i want layout rotation.
layout
<FrameLayout
android:id="#+id/fl_main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imgPhotoEditorClose"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="top|start"
android:elevation="1dp"
android:src="#drawable/ic_remove" />
<FrameLayout
android:id="#+id/frmBorder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:background="#drawable/rounded_border_tv">
<ImageView
android:id="#+id/imgPhotoEditorImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="#string/app_name"
android:scaleType="fitCenter"
android:src="#drawable/ic_remove" />
</FrameLayout>
<ImageView
android:id="#+id/imgPhotoEditorPush"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="bottom|end"
android:elevation="1dp"
android:src="#drawable/ic_remove" />
java
final View imageRootView = getLayout(ViewType.IMAGE);
final ImageView imageView = imageRootView.findViewById(R.id.imgPhotoEditorImage);
final FrameLayout frmBorder = imageRootView.findViewById(R.id.frmBorder);
final ImageView imgClose = imageRootView.findViewById(R.id.imgPhotoEditorClose);
final ImageView imgPhotoEditorPush = imageRootView.findViewById(R.id.imgPhotoEditorPush);
imgPhotoEditorPush.setOnTouchListener(new View.OnTouchListener()
{
float centerX, centerY, startR, startScale, startX, startY;
float startAngle;
float zeroAngle;
int firstPointX;
int firstPointY;
public boolean onTouch(View v, MotionEvent e)
{
if (e.getAction() == MotionEvent.ACTION_DOWN)
{
// calculate center of image
centerX = (imageRootView.getLeft() + imageRootView.getRight()) / 2f;
centerY = (imageRootView.getTop() + imageRootView.getBottom()) / 2f;
// recalculate coordinates of starting point
startX = e.getRawX() - imgPhotoEditorPush.getX() + centerX;
startY = e.getRawY() - imgPhotoEditorPush.getY() + centerY;
// get starting distance and scale
startR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
startScale = imageRootView.getScaleX();
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
imageRootView.getLocationOnScreen(locationOfLayout);
imgPhotoEditorPush.getLocationOnScreen(locationOfDrag);
firstPointX = locationOfLayout[0];
firstPointY = locationOfLayout[1];
float secondPointX = e.getRawX();
float secondPointY = e.getRawY();
zeroAngle = findRotation(firstPointX, firstPointY, secondPointX, secondPointY); // remember
// "zero"
// angle
startAngle = imageRootView.getRotation(); // remember angle at
// which layout is
// rotated at the start
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
// calculate new distance
float newR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
// set new scale
float newScale = newR / startR * startScale;
imageRootView.setScaleX(newScale);
imageRootView.setScaleY(newScale);
// move handler image
imgPhotoEditorPush.setX(centerX + imageRootView.getWidth() / 2f * newScale);
imgPhotoEditorPush.setY(centerY + imageRootView.getHeight() / 2f * newScale);
imageRootView.setRotation(findRotation(firstPointX, firstPointY, e.getRawX(), e.getRawY()) - zeroAngle + startAngle); // rotate relative to start and zero
// angle
}
else if (e.getAction() == MotionEvent.ACTION_UP)
{
}
return true;
}
});
Please help me.Thaks.
Related
I'm using FloatingActionMenu. In the below picture I have color the background with green color so it easy to understand the problem
I want to move the FloatingActionMenu when the user drags the pink color button. I wrote a function to move the button by getting the motion event as below
fab1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
int action = motionEvent.getAction();
if (action == MotionEvent.ACTION_DOWN) {
downRawX = motionEvent.getRawX();
downRawY = motionEvent.getRawY();
dX = view.getX() - downRawX;
dY = view.getY() - downRawY;
return true; // not Consumed for ripple effect
} else if (action == MotionEvent.ACTION_MOVE) {
viewWidth = view.getWidth();
viewHeight = view.getHeight();
View viewParent = (View) view.getParent();
parentWidth = viewParent.getWidth();
parentHeight = viewParent.getHeight();
newX = motionEvent.getRawX() + dX;
newX = Math.max(layoutParams.leftMargin, newX); // Don't allow the FAB past the left hand side of the parent
newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // Don't allow the FAB past the right hand side of the parent
newY = motionEvent.getRawY() + dY;
newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent
newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, newY); // Don't allow the FAB past the bottom of the parent
view.animate()
.x(newX)
.y(newY)
.setDuration(0)
.start();
return true; // Consumed
} else if (action == MotionEvent.ACTION_UP) {
float upRawX = motionEvent.getRawX();
float upRawY = motionEvent.getRawY();
float upDX = upRawX - downRawX;
float upDY = upRawY - downRawY;
if (newX > ((parentWidth - viewWidth - layoutParams.rightMargin) / 2)) {
newX = parentWidth - viewWidth - layoutParams.rightMargin;
} else {
newX = layoutParams.leftMargin;
}
view.animate()
.x(newX)
.y(newY)
.setInterpolator(new OvershootInterpolator())
.setDuration(300)
.start();
if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click
if (customClickListener != null) {
customClickListener.onClick(view);
}
return false;// not Consumed for ripple effect
} else { // A drag
return false; // not Consumed for ripple effect
}
} else {
return true;
}
}
});
But It won't be working as my requirement. I want to move the button when I'm drag from the pink color button. But it moving when I drag from the green color background. Not from the pink color area. How to add touchlistener only to the round icon only?
current XML file is
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<com.github.clans.fab.FloatingActionMenu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="http://schemas.android.com/tools"
android:id="#+id/fab_menu_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#color/colorPrimary"
app:fab_colorNormal="#DA4336"
app:fab_colorPressed="#E75043"
app:fab_colorRipple="#99FFFFFF"
app:fab_shadowColor="#66000000"
app:fab_showShadow="true"
app:menu_backgroundColor="#DA4336"
app:menu_labels_colorNormal="#333333"
app:menu_labels_colorPressed="#444444"
app:menu_labels_colorRipple="#66FFFFFF"
app:menu_labels_ellipsize="end"
app:menu_labels_maxLines="-1"
app:menu_labels_position="left"
app:menu_labels_showShadow="true"
app:menu_labels_singleLine="true"
app:menu_openDirection="up">
<com.github.clans.fab.FloatingActionButton
android:id="#+id/fab_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/fab_add"
app:fab_label="kkjj"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="#+id/fab_scan_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/fab_add"
app:fab_label="lljjl"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="#+id/fab_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/fab_add"
app:fab_label="jkjkjkj"
app:fab_size="mini" />
</com.github.clans.fab.FloatingActionMenu>
</RelativeLayout>
Try to use event.getX() instead of getRawX().
Code below works for me:
// below are declared as fields
float downX;
float downY;
float dx;
float dy;
// set on touch listener
fab.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
dx += event.getX() - downX;
dy += event.getY() - downY;
fab.setTranslationX(dx);
fab.setTranslationY(dy);
break;
case MotionEvent.ACTION_UP:
fab.performClick();
break;
}
return true;
}
});
Read your code again, seems like not only you want to drag the fab, but also you want to limit it to its parent area, so you need to do the limitation in ACTION_MOVE, by comparing the fab's bound and its parent's boundary.
i want to rotate a relative layout by a rotation button.
this is my code
main.java
imageContainer = (RelativeLayout)findViewById(R.id.imageContainer);
rotateBTN = (Button)findViewById(R.id.rotate);
rotateBTN.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final float xc = imageContainer.getWidth() / 2;
final float yc = imageContainer.getHeight() / 2;
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
imageContainer.clearAnimation();
mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
break;
}
case MotionEvent.ACTION_MOVE: {
mPrevAngle = mCurrAngle;
mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
animate(mPrevAngle, mCurrAngle, 0);
break;
}
case MotionEvent.ACTION_UP : {
rotate = false;
mPrevAngle = mCurrAngle = 0;
break;
}
}
return true;
}
});
private void animate(double fromDegrees, double toDegrees, long durationMillis) {
final RotateAnimation rotate = new RotateAnimation((float) fromDegrees, (float) toDegrees,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(durationMillis);
rotate.setFillEnabled(true);
rotate.setFillAfter(true);
imageContainer.startAnimation(rotate);
// imageView2.startAnimation(rotate);
System.out.println(mCurrAngle);
}
main.xml
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:id="#+id/onlyImage"
android:layout_marginTop="20dp">
<ImageView
android:id="#+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_launcher"
/>
<ImageView
android:id="#+id/imageView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_launcher"
android:visibility="gone"
/>
</RelativeLayout>
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:id="#+id/rotate"
/>
</RelativeLayout>
by this code, i am able to rotate the RelativeLayout. But the problem is that after rotating first time (rotate button also rotates because it is inside my RelativeLayout) ontouch event is not called on new position of my rotate button but if i touch the top left corner of my relative layout ( initial position of my button) onTouch listener works fine.
plz help me find the issue. any suggestion would be appreciated :)
this is my relative layout
P.S i want to do something like this
I want to make the design like image and also display same in phone and 7 inch tab.
I am using Linear layout by dividing the view in 5 part of the screen with using Framlayout draw a line but not possible to achieve like this image.
What's the other option like using canvas or any other better option.
First Image is displing expected result.
and other two are getting result.
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<gradient
android:angle="360.0"
android:endColor="#A29AA4"
android:startColor="#A29AA4" />
</shape>
Below layout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="5">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<View
android:id="#+id/mView_circle1"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#drawable/circleshape" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<View
android:id="#+id/mView_circle2"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#drawable/circleshape" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<View
android:id="#+id/mView_circle3"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#drawable/circleshape" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<View
android:id="#+id/mView_circle4"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#drawable/circleshape" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<View
android:id="#+id/mView_circle5"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#drawable/circleshape" />
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical"
android:background="#A29AA4">
</RelativeLayout>
</FrameLayout>
This is easier and cleaner in canvas. Here is how you would do the first one.. You can replicate this with slight modifications for the other two.
Create a Canvas View:
public class CanvasView extends View {
Paint bPaint;
RectF coordbounds;
public CanvasView(Context context) {
super(context);
}
private void init()
{
bPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bPaint.setStyle(Paint.Style.FILL_AND_STROKE);
bPaint.setColor(Color.BLACK);
}
#Override
public void onDraw(android.graphics.Canvas canvas)
{
super.onDraw(canvas);
canvas.drawLine(coordbounds.left,coordbounds.centerY(),
coordbounds.right,coordbounds.centerY(),bPaint);
int circledia=20;
//Divide the line into four segments and subtract 2 * half the radii
float actualspan = (coordbounds.right - coordbounds.left) - (2 * circledia/2);
//Segment the line into 3 parts
float interlinesegments = actualspan/(4-1);
for(int i=0; i<4;i++)
{
canvas.drawCircle(coordbounds.left + circledia/2 +
(i*interlinesegments),
coordbounds.centerY(),10,bPaint);
}
}
}
Create a layout to hold the view and call this view in your activity:
LinearLayout layout = (LinearLayout) findViewById(R.id.root);
CanvasView view = new CanvasView(this);
layout.addView(view);
oops, I forgot . :-) Please add this method in CanvasView class to declare the bounding box and set the layout:
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
float xpad = (float) (getPaddingLeft() + getPaddingRight());
float ypad = (float) (getPaddingTop() + getPaddingBottom());
float coww = 0.0f, cohh = 0.0f, coll = 0.0f;
init();
coww = (float) w - xpad;
cohh = (float) h - ypad;
// Create a bounding box
coordbounds = new RectF(0.0f,0.0f,
coww,cohh);
}
EDIT : Change the above methods for bitmap
private void init()
{
bPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bPaint.setStyle(Paint.Style.FILL_AND_STROKE);
bPaint.setColor(Color.BLACK);
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.button);
}
Change onDraw as follows:
#Override
public void onDraw(android.graphics.Canvas canvas)
{
super.onDraw(canvas);
canvas.drawLine(coordbounds.left,coordbounds.centerY(),
coordbounds.right,coordbounds.centerY(),bPaint);
int rectwidth=bitmap.getWidth();
int rectheight=bitmap.getHeight();
//Divide the line into four segments and subtract 2 * half the radii
float actualspan = (coordbounds.right - coordbounds.left) - (2 * rectwidth/2);
//Segment the line into 3 parts
float interlinesegments = actualspan/(4-1);
for(int i=0; i<4;i++)
{
float left= coordbounds.left + (i * interlinesegments);
float top= coordbounds.centerY()-rectheight/2;
float right = coordbounds.left+(i * interlinesegments)+rectwidth;
float bottom= coordbounds.centerY()+ rectheight/2;
canvas.drawBitmap(bitmap,null,new RectF(left,top,right,bottom),null);
}
}
With the help of above code and previous code I made this Combination of circle shape and bitmap.
#Override
public void onDraw(android.graphics.Canvas canvas)
{
super.onDraw(canvas);
canvas.drawLine(coordbounds.left, coordbounds.centerY(),
coordbounds.right, coordbounds.centerY(), bPaint);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_myprofile);
int rectwidth=bitmap.getWidth();
int rectheight=bitmap.getHeight();
//Divide the line into four segments and subtract 2 * half the radii
float actualspan_image = (coordbounds.right - coordbounds.left) - (2 * rectwidth/2);
//Segment the line into 3 parts
float interlinesegments_bitmap = actualspan_image / (4 - 1);
int circledia = 20;
//Divide the line into four segments and subtract 2 * half the radii
float actualspan = (coordbounds.right - coordbounds.left) - (2 * circledia/2);
//Segment the line into 3 parts
float interlinesegments = actualspan/(4-1);
for(int i=0; i<4;i++)
{
float left= coordbounds.left + (i * interlinesegments_bitmap);
float top= coordbounds.centerY()-rectheight/2;
float right = coordbounds.left+(i * interlinesegments_bitmap)+rectwidth;
float bottom= coordbounds.centerY()+ rectheight/2;
if(i==1){
canvas.drawBitmap(bitmap,null,new RectF(left,top,right,bottom),null);
}else{
canvas.drawCircle(coordbounds.left + circledia / 2 +
(i * interlinesegments),
coordbounds.centerY(), 10, bPaint);
}
}
}
I would like to implement Word Search app. As part of implementation i have come across canvas and drawing line over grid view cells( letters that form the word) to indicate that user is touching finger over letters to form the word.
I have succeeded partially as of now i can draw a line over letters of grid view but the line is not through center of views of grid View.
Please can anyone assist me with your valuable suggestions .
Have a glance on below screen shot to get a clear idea.
Edited: I'm posting code to get an idea of how I'm implementing it.
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#fff" >
<RelativeLayout
android:id="#+id/topbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#A9E2F3" >
<LinearLayout
android:id="#+id/topbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#336699"
android:orientation="horizontal" >
<Button
android:id="#+id/btn_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pause" />
<Chronometer
android:id="#+id/chronometer1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Chronometer" />
<TextView
android:id="#+id/counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="20sp"
android:typeface="serif" />
</LinearLayout>
</RelativeLayout>
<FrameLayout
android:id="#+id/gridFrame"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/wTable"
android:layout_below="#+id/textdisplay" >
<GridView
android:id="#+id/grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#E7E8E9"
android:fitsSystemWindows="true"
android:gravity="center"
android:horizontalSpacing="10sp"
android:numColumns="10"
android:padding="1dp"
android:stretchMode="columnWidth"
android:verticalSpacing="10sp" >
</GridView>
</FrameLayout>
<GridView
android:id="#+id/wTable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#fff"
android:numColumns="3"
android:orientation="vertical" />
</RelativeLayout>
The paint is drawing over frame layout which contains grid view. Grid view elements are printed through custom text view file.
To draw a line i have used LineView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
public class LineView extends View {
public static final float LINE_WIDTH = 30.0f;
public Paint paint = new Paint();
protected Context context;
public float startingX, startingY, endingX, endingY;
public LineView(Context context) {
super(context);
this.context = context;
paint.setColor(Color.parseColor("#2E9AFE"));
paint.setStrokeWidth(LINE_WIDTH);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setDither(true);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setAlpha(90);
}
public void setPoints(float startX, float startY, float endX, float endY) {
startingX = startX;
startingY = startY;
endingX = endX;
endingY = endY;
invalidate();
}
#Override
public void onDraw(Canvas canvas) {
Log.e("LINEVIEW", "startingX" + startingX + " startingY:" + startingY);
Log.e("LINEVIEW", "endingX" + endingX + " endingY:" + endingY);
// canvas.drawLine(startingX, startingY, endingX, endingY, paint);
canvas.drawLine(startingX, startingY, endingX, endingY, paint);
}
}
Main Activity where logic is implemented:
Written only the required logic here.
newGrid = (GridView) findViewById(R.id.grid);
newGrid.setAdapter(new FormTheGridLetters());
newGrid.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// if (mp.isPlaying()) {
// mp.stop();
// }
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
// data
PaintViewHolder newPaint = new PaintViewHolder();
newPaint.DrawLine = new LineView(WordSearchActivity.this);
gridFrame.addView(newPaint.DrawLine);
buildWord = new StringBuilder();
int x = (int) event.getX();
int y = (int) event.getY();
// test = new LineView(WordSearchActivity.this);
int position = newGrid.pointToPosition(x, y);
Point one,
two;
if (position != GridView.INVALID_POSITION) {
v.getParent().requestDisallowInterceptTouchEvent(true);
cellView = (TextView) newGrid.getChildAt(position);
String a = cellView.getText().toString();
// Log.v(">>>>><<<<<<<????????", a.toString());
switch (action) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
// Checking the list for formed word ;
//if found that is painted
for (int i1 = 0; i1 < Ans.size(); i1++)
{
if (formedWord.equals(Ans.get(i1)))
{
answerAdapter.notifyDataSetChanged();
newPaint.DrawLine.setPoints(startX, startY, x, y);
// Painted the letters by passing starting and ending points
}
}
break;
}
} else {
if (mSelecting) {
mSelecting = false;
}
}
break;
case MotionEvent.ACTION_CANCEL:
mSelecting = false;
break;
}
return true;
}
});
I don't know if you fix the issue but I will answer anyway for the people that may have these kind of problems. After you recieve the valid position, you can get the center of the view and you can set these values as beginning of the draw.
Like this:
if (position != GridView.INVALID_POSITION) {
MyList.add(position);
v.getParent().requestDisallowInterceptTouchEvent(true);
TextView cellView = (TextView) gridView.getChildAt(position);
centreX = cellView.getX() + cellView.getWidth() / 2;
centreY = cellView.getY() + cellView.getHeight() / 2;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
newPaint.DrawLine.touch_start(x, y,centreX,centreY);
I have tried this code and it is working. I don't think that you need anymore but I have joined this site recently so maybe it will help other people. I can post more code if you want but
newPaint.DrawLine.touch_start(x, y,centreX,centreY);
is the trick for that issue.
Hope this helps.
I'm currently working on an app that has a RelativeLayout that has 4 child FrameLayouts, each FrameLayout has a set of ImageViews inside it and the inside View has it's own behavior. I'm trying to implement a drag and drop to theFrameLayouts while implementing the onTouchListener I found in this tutorial. but unfortunately the drag 'n drop doesn't work properly and nothing is happening.
any thoughts on how to implement the drag and drop correctly? what am I missing?
here is the xml code for a single child of the FrameLayouts:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="108dp" >
<ImageView
android:id="#+id/secondImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/back" />
<ImageView
android:id="#+id/firstImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/c2" />
</FrameLayout>
here is the xml code for the main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/pinecropped"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/cardNumber1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginTop="60dp" >
<include layout="#layout/card" />
</FrameLayout>
<FrameLayout
android:id="#+id/cardNumber2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/cardNumber1"
android:layout_marginLeft="50dp"
android:layout_marginTop="100dp" >
<include layout="#layout/card" />
</FrameLayout>
<FrameLayout
android:id="#+id/cardNumber3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="50dp"
android:layout_marginTop="60dp" >
<include layout="#layout/card" />
</FrameLayout>
<FrameLayout
android:id="#+id/cardNumber4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/cardNumber3"
android:layout_marginRight="50dp"
android:layout_marginTop="100dp" >
<include layout="#layout/card" />
</FrameLayout>
</RelativeLayout>
here is the Java code for the single child:
public class Card implements OnClickListener {
private int _resId;
private Context _context;
private ImageView firstImage, secondImage;
private boolean isFirst;
public Card(Context context, FrameLayout parent) {
_context = context;
firstImage = (ImageView) parent.findViewById(R.id.firstImage);
secondImage = (ImageView) parent.findViewById(R.id.secondImage);
}
public void setupCards(int resId, boolean hasBackSide) {
_resId = resId;
Bitmap temp = BitmapFactory.decodeResource(_context.getResources(),
_resId);
firstImage.setImageBitmap(temp);
if (hasBackSide) {
temp = BitmapFactory.decodeResource(_context.getResources(),
R.drawable.back);
}
secondImage.setImageBitmap(temp);
isFirst = true;
secondImage.setVisibility(View.GONE);
}
// MORE IMPLEMENTATION
}
this is my main activity Java code:
public class FaceUpActivity extends Activity {
FrameLayout firstCard, secondCard, thirdCard, forthCard;
Card cardNumber1, cardNumber2, cardNumber3, cardNumber4;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initUI();
}
private void initUI() {
firstCard = (FrameLayout) findViewById(R.id.cardNumber1);
secondCard = (FrameLayout) findViewById(R.id.cardNumber2);
thirdCard = (FrameLayout) findViewById(R.id.cardNumber3);
forthCard = (FrameLayout) findViewById(R.id.cardNumber4);
cardNumber1 = new Card(this, firstCard);
cardNumber2 = new Card(this, secondCard);
cardNumber3 = new Card(this, thirdCard);
cardNumber4 = new Card(this, forthCard);
cardNumber1.setupCards(R.drawable.c2, true);
cardNumber2.setupCards(R.drawable.d0, true);
cardNumber3.setupCards(R.drawable.h5, true);
cardNumber4.setupCards(R.drawable.sj, true);
firstCard.setOnTouchListener(dragMe);
secondCard.setOnTouchListener(dragMe);
thirdCard.setOnTouchListener(dragMe);
forthCard.setOnTouchListener(dragMe);
}
OnTouchListener dragMe = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
FrameLayout.LayoutParams params = (LayoutParams) v
.getLayoutParams();
int maxWidth = getWindowManager().getDefaultDisplay().getWidth();
int maxHeight = getWindowManager().getDefaultDisplay().getHeight();
int topMargin, leftMargin;
int cond = v.getId();
if (cond == R.id.cardNumber1 || cond == R.id.cardNumber2
|| cond == R.id.cardNumber3 || cond == R.id.cardNumber4) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
topMargin = (int) event.getRawY() - (v.getHeight());
leftMargin = (int) event.getRawX() - (v.getWidth()) / 2;
if (topMargin < 0) {
params.topMargin = 0;
} else if (topMargin > maxHeight) {
params.topMargin = maxHeight - v.getHeight();
} else {
params.topMargin = topMargin;
}
if (leftMargin < 0) {
params.leftMargin = 0;
} else if (leftMargin > maxWidth) {
params.leftMargin = maxWidth - (v.getWidth() / 2);
} else {
params.leftMargin = leftMargin;
}
v.setLayoutParams(params);
break;
case MotionEvent.ACTION_MOVE:
topMargin = (int) event.getRawY() - (v.getHeight());
leftMargin = (int) event.getRawX() - (v.getWidth()) / 2;
if (topMargin < 0) {
params.topMargin = 0;
} else if (topMargin > maxHeight) {
params.topMargin = maxHeight - v.getHeight();
} else {
params.topMargin = topMargin;
}
if (leftMargin < 0) {
params.leftMargin = 0;
} else if (leftMargin > maxWidth) {
params.leftMargin = maxWidth - (v.getWidth() / 2);
} else {
params.leftMargin = leftMargin;
}
v.setLayoutParams(params);
break;
}
}
return true;
}
};
}
Why your D&D is not working:
D&D is not working because your Card (that useses the internal FrameLayout) is implementing the onClick event that "eat" the d&d event.
Solutions are two:
you can have 2 different areas, one for the click event (the biggest part of the card), one for the d&d event (the bottom-left edge of the card). You can see a live example in the Android Music player that implements this solution.
Otherwise you can handle the two events at the same time:
click == down+up in the same time (under 100ms) in the same x/y location
dd == down+up in different times ( > 50/100ms)
I think there are a couple of potential problems:
Are you sure you're getting the correct IDs in your onTouch()? (since the touch listener is only used with your card views, you propably can remove the if checking for the IDs)
You are using a FrameLayout - so use the x and y position instead of margins edit: my bad, you're using RelativeLayout, so the margins are kind of right. Though, I'd use a FrameLayout instead
the API says you need to return true in onTouch() if you consumed the event, false otherwise (you're returning true when you didn't move the cards and nothing when you did)