I am showing camera preview on top using system alert. And I am trying to make it draggable. Initially I am drawing it on top left conrner. But on dragging it, it just comes to the center of the screen and doesn't move after that.
Here is how I am adding relative layout :
RelativeLayout.LayoutParams sf_lp = new RelativeLayout.LayoutParams(xlen,ylen);
relativeLayout.addView(surfaceView,sf_lp);
WindowManager.LayoutParams wLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,0,0,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT);
wLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
windowManager.addView(relativeLayout,wLayoutParams);
Here is the code for OnTouch :
public boolean onTouch(View v, MotionEvent event) {
int X = (int) event.getRawX();
int Y = (int) event.getRawY();
int xpos = relativeLayout.getLeft();
int ypos = relativeLayout.getTop();
if(X >= xpos && X <= xpos+relativeLayout.getWidth() && Y >= ypos && Y <= ypos+relativeLayout.getHeight())
{
Toast.makeText(this,"X="+X+", "+"Y="+Y+"-Touched inside",Toast.LENGTH_SHORT).show();
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN :
WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) v.getLayoutParams();
dx = X - wlp.x;
dy = Y - wlp.y;
Log.v("onTouch", "Action Down:X=" + X + ", Y=" + Y + " ,dx=" + dx + " ,dy=" + dy);
break;
case MotionEvent.ACTION_UP : Log.v("onTouch","Action Up:X="+X+", Y="+Y+" ,dx="+dx+" ,dy="+dy);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE :
//windowManager.removeView(v);
Log.v("ACTION_MOVE","X="+ (X-dx) +"Y="+ (Y-dy));
//((TextView) v.findViewWithTag("tv")).setText("X="+ (X-dx) +"Y="+ (Y-dy));
WindowManager.LayoutParams wlp1 = new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT);
wlp1.x = X-dx;
wlp1.y = Y-dy;
windowManager.updateViewLayout(v,wlp1);
//windowManager.addView(v,wlp1);
//v.animate().x(X-dx).y(Y-dy).setDuration(0).start();
Log.v("onTouch", "Action Move:X=" + X + ", Y=" + Y + " ,dx=" + dx + " ,dy=" + dy);
break;
}
}
else
{
Toast.makeText(this,"X="+X+", "+"Y="+Y+"-Touched Outside",Toast.LENGTH_SHORT).show();
}
return false;
}
As you can see in Action Move I have already tried removing the view and the adding it again with new layout parameters but it does the same thing. I can drag a button in an activity with this same code but not this. What am I doing wrong?
I had tried the same using below code and using surfaceview directly rather than relative layout
preview.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(preview, params);
return true;
}
return false;
}
});
Finally I found what was causing it. The problem was with the 'if' condition where I was trying to determine if user has touched inside the view or outside. It wasn't updating the location of relative layout after dragging.
int xpos = relativeLayout.getLeft();
int ypos = relativeLayout.getTop();
if(X >= xpos && X <= xpos+relativeLayout.getWidth() && Y >= ypos && Y <= ypos+relativeLayout.getHeight())
{
}
I commented the if condition and its working as expected. But I am not sure what was problem with 'getLeft()' and 'getTop()'. I also tried 'getLocationInWindow()' but it didn't update the relative layout's location in screen too. If anyone finds the problem please share. And thanks for your help.
Related
I have a LinearLayout that contains some other views. I have implemented onTouchListener over it and I want to move it with user gesture. but it has some other views inside it, that have there on click listeners. I have an ImageView and 2 buttons in this layout and these views have there own click listeners. just have a look at layout.
I can only move my layout when user click on Free space and then start dragging. whereas I want to move layout even though user start dragging from over
Imageview,btn1 or Btn2.
I know because BTN1,2 and ImageView are set to be clickable that is why they are consuming onTouchListener of LinearLayout. Here is some code of touchListener
#Override
public boolean onTouch(View mView, MotionEvent event) {
View view = null;
if(!(mView instanceof LinearLayout) && !(mView instanceof RelativeLayout)){
view = (View)(mView.getParent().getParent().getParent());
}else{
view = mView;
}
final int X = (int) event.getRawX();
//final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
Log.d("TTP", "X_Delta " + _xDelta + " X " + X + " left margin " + lParams.leftMargin);
break;
case MotionEvent.ACTION_UP:
int notMoved = X - _xDelta;
if(notMoved == 0){
Log.d("TTP", "ACTION UP ");
return false;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
Log.d("TTP", "POINTER UP ");
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
int mTotalMargin = X - _xDelta;
boolean isMovingRight = mTotalMargin > 0;
if ((isMovingRight && mTotalMargin < (getScreenWidth() / 2)) || (!isMovingRight && mTotalMargin > (getScreenWidth() / -2))) {
layoutParams.leftMargin = mTotalMargin;
layoutParams.rightMargin = mTotalMargin * -1;
view.setLayoutParams(layoutParams);
Log.d("TTP", "Mov X_Delta " + _xDelta + " X " + X + " getScreenWidth " + getScreenWidth() + " TotalMargin " + mTotalMargin + " " + isMovingRight);
}
break;
case MotionEvent.ACTION_CANCEL:
Log.d("TTP", "CANCEL ");
return false;
}
return true;
}
**So my question is how can I bypass dragging operation from BTN1,2 and ImageView to LinearLayout regardless of their click events. Please help me I am stuck here **
I am developing an android application, in my application I dynamically create some ImageViews and set that ImageViews in to a RelativeLayout. So I want to drag each image in the layout independently.Now its working but not properly, when I drag image then the image start vibrating and moving slowly. And I wanted to implement Pinch Zoom in this image.Is it possible? And how how can I remove the vibration on moving the image ? If any one know it please help me..
Thanks
This is my onTouchListener()
canvasImage[i].setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
x1 = motionEvent.getX();
y1 = motionEvent.getY();
//Log.v("vvvvvv", "" + x1 + " " + y1);
final int action = motionEvent.getAction();
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
String w = imglayout.getTop() + " " + imglayout.getHeight();
Log.v("wwww", "" + w);
x2 = motionEvent.getX();
y2 = motionEvent.getY();
dx = x2 - canvasImage[finalI].getX();
dy = y2 - canvasImage[finalI].getY();
//Log.v("cccccc", "" + x2 + " " + y2);
moving = true;
break;
case MotionEvent.ACTION_UP:
moving = false;
break;
case MotionEvent.ACTION_MOVE:
if (moving) {
canvasImage[finalI].setX(motionEvent.getX() - dx);
canvasImage[finalI].setY(motionEvent.getY() - dy);
//Log.v("qqqqqq", "" + canvasImage[finalI].getX());
}
break;
}
//mainLayout.invalidate();
return true;
}
});
This is my setCanvasImage() method used to set images into RelativeLayout
public void setCanvasImage() {
int screenSize = getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK;
final int imgCount = dbobj.getFromTemp();
canvasImage = new ImageView[imgCount];
imglayout = (RelativeLayout) findViewById(R.id.canvas);
final String[] strImage = dbobj.getdImage();
imglayout.removeAllViews();
for (int i = 0; i < imgCount; i++) {
canvasImage[i] = new ImageView(this);
canvasImage[i].setTag("img_" + i);
boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
int imgWidth = 130;
int imgHeight = 130;
RelativeLayout.LayoutParams paramss = new RelativeLayout.LayoutParams(imgWidth, imgHeight);
paramss.setMargins(posLeft, posTop, 0, 0);
canvasImage[i].setLayoutParams(paramss);
canvasImage[i].setScaleType(ScaleType.FIT_XY);
canvasImage[i].setTag(strImage[i]);
setImage(strImage[i], canvasImage[i]);
imglayout.addView(canvasImage[i]);
}
if( screenSize == Configuration.SCREENLAYOUT_SIZE_NORMAL){
int imgWidth = 100;
int imgHeight = 100;
RelativeLayout.LayoutParams paramss = new RelativeLayout.LayoutParams(imgWidth, imgHeight);
paramss.setMargins(posLeft, posTop, 0, 0);
canvasImage[i].setLayoutParams(paramss);
canvasImage[i].setTag(strImage[i]);
setImage(strImage[i], canvasImage[i]);
imglayout.addView(canvasImage[i]);
}
posLeft = posLeft + 15;
}
}
RelativeLayout xml file
<RelativeLayout
android:layout_below="#+id/btnhorscrolvw"
android:layout_width="match_parent"
android:layout_height="500dp"
android:id="#+id/canvas"
android:background="#ffff"
android:orientation="horizontal"
>
</RelativeLayout>
I think this will work.
float dX, dY;
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
view.animate()
.x(event.getRawX() + dX)
.y(event.getRawY() + dY)
.setDuration(0)
.start();
break;
default:
return false;
}
return true;
}
You need to use scalx and scaley factor of imageview for implementing pinch zooming
imageview.setScaleX(scalefactor);
imageview.setScaleY(scalefacto);
Android you can adjust the margin left and margin top to for draging the imageview
I'm trying to make a view invisible when it's dragged to a certain Y coordinate on the screen.
This is what I got now:
private final class dragTouchListener implements View.OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
ContentFrameLayout.LayoutParams lParams = (ContentFrameLayout.LayoutParams) v.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
trash_image.setVisibility(View.INVISIBLE);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
trash_image.setVisibility(View.VISIBLE);
ContentFrameLayout.LayoutParams layoutParams = (ContentFrameLayout.LayoutParams) v.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
v.setLayoutParams(layoutParams);
if(v.getY() > trash_image.getY()){
v.setVisibility(View.INVISIBLE);
}
break;
}
contentView.invalidate();
return true;
}
}
So basically what I've tried here is simply an if statement to check if the Y position of the view has "passed" that of another ImageView placed on the upper part of the screen. This however result in becoming invisible as soon as I touch the view to be dragged, no matter where on the screen it's located. So it's far from accurate, or wrong all together.
As requested in comment, a suggestion (do note I had to change it, since this is for a client program, so I didnt test it again):
First, discover SCREEN_DENSITY
private static float SCREEN_DENSITY = getResources().getDisplayMetrics().density;
The onTouch function:
public boolean onTouch(final View v, MotionEvent event) {
case MotionEvent.ACTION_DOWN:
mainFinger = new Point(
(int) (event.getRawX() / SCREEN_DENSITY),
(int) (event.getRawY() / SCREEN_DENSITY)
);
break;
case MotionEvent.ACTION_MOVE:
movFrame(
(FrameLayout) v,
(int) (event.getRawX() / SCREEN_DENSITY),
(int) (event.getRawY() / SCREEN_DENSITY)
);
}
movFrame function:
private void movFrame(FrameLayout v, int movX, int movY) {
MyObject p = (MyObject ) v.getTag();
int[] x, y, h, w;
x = p.x;
y = p.y;
h = p.h;
w = p.w;
x = p.x + movX - mainFinger.x;
mainFinger.x = movX;
if (x + w > p.parent.w) {
x = p.parent.w - w;
}
if (x < 0) {
x = 0;
}
y = p.y + movY - mainFinger.y;
mainFinger.y = movY;
if (y + h > p.parent.h) {
y = p.parent.h - h;
}
if (y < 0) {
y = 0;
}
p.updateMyObject(x, y, h, w);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
(int) ((p.w * SCREEN_DENSITY) + 0.5),
(int) ((p.h * SCREEN_DENSITY) + 0.5)
);
params.leftMargin = (int) ((p.x * SCREEN_DENSITY) + 0.5);
params.topMargin = (int) ((p.y * SCREEN_DENSITY) + 0.5);
v.setLayoutParams(params);
}
I have a draggable image and I'm trying to get it so that if it goes within an X Y region of the screen that an event happens.
So far I can detect when I move a finger through the region but not when it is dragging the image.
The code so far: - this code works for the finger
public boolean onTouchEvent(MotionEvent ev) {
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (x >= 370 && x <= 500 && y >= 250 && y <= 420) {
Log.i(null, "--- Region 1 initiated ---");
}
What I've tried: - but when I try to adapt it to the image...
public boolean onDrag(View layoutview, DragEvent dragevent) {
int action = dragevent.getAction();
View getid = findViewById(R.id.image);
int x1 = (int) getid.getX();
int y1 = (int) getid.getY();
if (action == MotionEvent.ACTION_MOVE) {
if (x1 >= 370 && x1 <= 500 && y1 >= 250 && y1 <= 420) {
Log.i(null, "--- Region 1 initiated by image---");
}
}
...nothing happens. The logcat doesn't show the message. Does anyone know where I'm going wrong or if there's a way of doing this.
Some illustrations, sometimes my description of the problem is pretty bad:
It took a while but I actually got it working by doing this in onTouch:
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
ImageView j = (ImageView) findViewById(R.id.image);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
_xDelta = (int) (X - j.getTranslationX());
_yDelta = (int) (Y - j.getTranslationY());
break;
case MotionEvent.ACTION_UP:
_xDelta = 100;
_yDelta = 100;
break;
case MotionEvent.ACTION_MOVE:
j.setTranslationX(X - _xDelta);
j.setTranslationY(Y - _yDelta);
if (X >= 370 && X <= 500 && Y >= 250 && Y <= 420) {
Log.i(null, "Region 1 initiated");
// Do whatever...
}
There is no MotionEvent.ACTION_MOVE defined in DragEvent class
OnDragListener interface defined the method
abstract boolean onDrag(View v, DragEvent event)
Action are:
ACTION_DRAG_STARTED
ACTION_DRAG_ENTERED
ACTION_DRAG_LOCATION
ACTION_DRAG_EXITED
ACTION_DROP
ACTION_DRAG_ENDED
Please refer to this page for more details
I need a scrollview where I can add numbers of image and button programatically and on single tap, zoomable by pinch on both horizontal and vertical with smooth scrolling. Here a video what I need exactly. I have tried with Horizontal scrollview within a ScrollView. I can scroll smoothly. I can add item on single tap. I can't zoom now. Here is the sample code:
public void setUpNoticeBoard(){
canvasLayout = (FrameLayout) findViewById(R.id.frameLayout);
canvasLayout.removeAllViews();
FrameLayout.LayoutParams paramsImage = new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
final ImageView noticeBoard = new ImageView(this);
noticeBoard.setLayoutParams(paramsImage);
noticeBoard.setAdjustViewBounds(true);
noticeBoard.setImageDrawable(getResources().getDrawable(R.drawable.noticeboard));
noticeBoard.setScaleType(ImageView.ScaleType.CENTER_CROP);
canvasLayout.addView(noticeBoard);
float xx = noticeBoard.getWidth();
float yy = noticeBoard.getHeight();
System.out.println("noticeBoard Width:" + xx + "And Height:" + yy);
for (int i = 0; i < 50; i++) {
int x= (int)Math.ceil(Math.random()*3000);
int y= (int)Math.ceil(Math.random()*2000);
FrameLayout.LayoutParams paramsNotice = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
paramsNotice.setMargins(x, y, 0, 0);
final ImageView notice = new ImageView(this);
notice.setLayoutParams(paramsNotice);
Resources res = getResources();
String imageName = "pin" + (int)Math.ceil(Math.random()*8);
int resourceId = res.getIdentifier(imageName, "drawable", getPackageName() );
notice.setTag(imageName);
notice.setImageResource(resourceId);
canvasLayout.addView(notice);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float curX, curY;
newPin.setVisibility(View.INVISIBLE);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
break;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
mx = curX;
my = curY;
break;
case MotionEvent.ACTION_UP:
curX = event.getX();
curY = event.getY();
vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
break;
}
return gestureScanner.onTouchEvent(event);
}
public boolean onSingleTapUp(MotionEvent e) {
int x = (int) e.getX();
int y = (int) e.getY();
FrameLayout.LayoutParams paramsNewPin = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
paramsNewPin.setMargins(x + hScroll.getScrollX() - 98, y + vScroll.getScrollY() - 250, 0, 0);
final ImageView newPin = new ImageView(this);
newPin.setLayoutParams(paramsNewPin);
newPin.setImageResource(R.drawable.pin5);
canvasLayout.addView(newPin);
return true;
}
Now I need 1 thing Zooming on pinch(Whole content on layout will be zoom)
Thanks.