Clickable scrolling image - android

I have an activity which contains an image view that is scrollable -> the image is bigger than the phone's screen and therefore it is scrollable.
I want that several points of the image would be clickable.
how is it possible then if the image is scrollable and I also need to detect on which part of the image the user clicked?
thanks

Well you'll have to divide us the image in different portions if you want to provide that sort of functionality. Because an ImageView is one element which is capable of handling it's own trigger event for the whole image. It doesn't matter if you touch the middle, top-right, bottom-left, quarter to the right or anywhere. The only thing you can determine are the X and Y cordinators of where the touch was placed via the following function:
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
String xCordinate = String.valueOf(event.getX()
String yCordinate = String.valueOf(event.getY();
}
return true;
}
});
Additionally, if you want to handle a different events on a single image based on what part/portion of the image was clicked, you'll have to hide elements which will trigger the event. In this case, you can use a frameLayout with ImageView on the back and 4 buttons on the top (top-left, top-right, bottom-left, bottom-right) and hide the buttons using the following code:
button.setVisibility(View.GONE);
And base your functionality around the onClickListener for the buttons.
Hope I am making sense.

Related

listview drag listener apply to all views in layout

I have an app that uses the this library as a drag and drop activity to reorder items.
I adjusted the item layout to have two images and text (instead of one image and the text), and I moved the image that they click to drag to the far right. My problem is now the first image has the drag listener attached to it. (And if I put the text first and then the two images second, the listener applies only to the text). Is there a way I can choose which element has the drag listener, or make all of the elements have it.
It seems like its just giving it to the first child of the layout. I tried to just put all three views in a linear layout hoping that the linear layout would have the listener, but it just bypassed that and went to the first element of that layout.
OK i found it. I tried putting an invisible image first that stretched the entire width of the view, but it still only applied to the left part of the view.
Then I did some more digging and found this code in the DragNDropListView.java file
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
final int x = (int) ev.getX();
final int y = (int) ev.getY();
if (action == MotionEvent.ACTION_DOWN && x < this.getWidth()/4) {
mDragMode = true;
}
...
}
just change the this.getWidth()/4 to this.getWidth() to have it use the entire view instead of the first 1/4
EDIT: Do Not Do This If the list you are reordering does not fit on the screen, if the entire width is used you cannot scroll down the list

which layout displays multiple image buttons?

Hi I'm trying to add an activity that displays 4 images (imagine a square cut to quarters) where each image shows a different one when clicked, I have tried a few layouts using image buttons to no avail but then read here my answer is a grid view using image pager but when implementing this I get small images spaced quite far apart in grid view is there a better way please?
if it's always 2x2 images you can simply use a vertical linear layout and two horizontal layouts in it and then put your images as ImageButton or ImageView inside the horizontal layouts...
if it needs to be dynamic a gridlayout would probably be a good idea...
however, you need to provide more detailed information on what the issue is, if you need a more detailed answer...
(edit: I meant gridview, gridlayout is only available since api level 14)
You can use a RelativeLayout in order to add your ImageButtons and have all the control to your hands for location of buttons, size etc.
A different point of view, is to break your screen into 4 Rectangles (Rects).
Something like this :
Rect upLeftRect = new Rect(0,0,screenWidth/2 , screenHeight/2);
Rect upRightRect = new Rect(screenWidth/2,0,screenWidth,screenHeight/2);
Rect downLeftRect = new Rect(0,screenHeight/2, screenWidth/2 , screenHeight);
Rect downRightRect = new Rect(screenWidth/2, screenHeight/2, screenWidth,screenHeight);
The, attach an onTouchListener on your relativeLayout, something like this in your constructor:
yourRelativeLayout.setOnTouchListener(this);
And finally , inside the onTouch method you will have something like this :
#Override
public boolean onTouch(View v, MotionEvent e){
if(upLeftRect.contains( ( int ) e.getX(), (int) e.getY){
// do whatever you want, i guess that you want some alpha animation or something like this
}else if(upRightRect.contains( (int) e.getX(), (int) e.getY(){
// bla bla.. :)
} // do the rest conditions your self!!
Hope that helped!

Make INVISIBLE View handle touches as ACTION_OUTSIDE

I want to create transparent system overlay window, which has several round views:
Green view is VISIBLE, red one is INVISIBLE. The thing is that I need red view to pass touches to the underlying window, but by default it doesn't.
I tried setting visibility of red view to GONE, but then overall size of containing view changes. Since I need the containing view to be snapped to the right edge of the screen, this means that position of green view changes, and I don't want this.
Is there any way to override default touch handling in INVISIBLE state?
Here's an actual screenshot to make my question more clear:
Also, I had to override dispatchTouchEvent() to dispatch touch events correctly:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Circle target=null;
int targetIndex=-1;
for (int i=0; i<getChildCount(); i++) {
Circle child=(Circle) getChildAt(i);
if (child.viewMetrics.containsPoint(ev.getX(), ev.getY()) && (ev.getAction()==MotionEvent.ACTION_MOVE || child.isVisible())) {
target=child;
targetIndex=i;
break;
}
}
onMotionEvent(ev, target, targetIndex);
Log.d(">| CircularLayout", "action: "+ev.getAction()+", target: "+target);
return target!=null && target.dispatchTouchEvent(ev);
}
Create custom view to do this. In such case you do not need any trickery related to visible invisible - it's you who decide what is your clickable area and also you who decies what area will alter the state (like is drawn as pressed on touch event). So your custom view should be of the size of desired area but in your onDraw() you shall only draw the change on that smaller inner area.
Here are basics on how to create custom views: http://developer.android.com/training/custom-views/index.html
What I ended up doing is calculating two sets of view dimensions: maximum possible (size of the red area) and current (green area). When child view is hidden or shown I set width and height of window LayoutParams to current dimensions and then set difference between maximum and current dimensions to y and x parameters of LayoutParams.
For some reason applying modified LayoutParams triggers measure/layout pass twice (which in turn causes the view to "bounce"), but that seems to be the whole new story.

How to change image size when pressing

I'm currently developing an android app and I would like to achieve an effect to which I haven't found an answer to, even after some searching.
The effect I would like to obtain is over an image. Usually when you press an image, you apply some sort of tint over the image in order to show some feedback, but I would like to go a little bit further, I wouldn't like to apply a tint but a sort os scale over the image.
E.g. I have the following image, Normal Image, and if I press the image (and while I keep it pressed), I would like the image to shrink a bit, like this Pressed Image
N.B.- The black part would not be part of the image, but part of the background. The image would only be the blue square.
Thank you for any help! :)
P.S.- I couldn't post the images here because I don't have enough reputation.
You need to set the onTouchListener of your ImageView that displays the image, so that it replaces the displayed image. This is the listener that runs when you press or unpress the view (in this case the image).
Sample Code:
ImageView iv = (ImageView)findViewById(R.id.my_image_view);
iv.setOnTouchListener(new ImageView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
if (e.getAction()==MotionEvent.ACTION_DOWN)
// Write code here that sets the imageview to display the pressed image
else if (e.getAction()==MotionEvent.ACTION_UP)
// Write code here that sets the imageview to display the unpressed image
}
});
Reference to onTouchListener: http://developer.android.com/reference/android/view/View.OnTouchListener.html
Reference to ImageView (for replacing the displayed image):
http://developer.android.com/reference/android/widget/ImageView.html

how to use correct dragging of a view on android

it seems that there are a lot of solutions of how to use dragging of views on android .
however, they are either too slow or buggy.
a known solution is to have a framelayout , and the view simply changes its layoutParams as it moves using the OnTouchListener ,as described here:
http://www.anddev.org/novice-tutorials-f8/android-drag-and-drop-of-normal-views-not-bitmaps-t13404.html
however, if the view is an imageView , when reaching the most right (or most bottom) side of the framelayout , the image shrinks .
another possible solution is to use the canvas in order to show the dragged content , as described here:
http://www.anddev.org/basic_drag_and_drop-t3095.html
however, i'm not sure how to use it for complex views.
does anyone know of a good solution , one that let the size of the dragged view stay the same , no matter where it is in its container?
please help me .
Here's a complete solution for a simple imageView dragging:
findViewById(R.id.imageView).setOnTouchListener(new OnTouchListener()
{
int prevX,prevY;
#Override
public boolean onTouch(final View v,final MotionEvent event)
{
final FrameLayout.LayoutParams par=(FrameLayout.LayoutParams)v.getLayoutParams();
switch(event.getAction())
{
case MotionEvent.ACTION_MOVE:
{
par.topMargin+=(int)event.getRawY()-prevY;
prevY=(int)event.getRawY();
par.leftMargin+=(int)event.getRawX()-prevX;
prevX=(int)event.getRawX();
v.setLayoutParams(par);
return true;
}
case MotionEvent.ACTION_UP:
{
par.topMargin+=(int)event.getRawY()-prevY;
par.leftMargin+=(int)event.getRawX()-prevX;
v.setLayoutParams(par);
return true;
}
case MotionEvent.ACTION_DOWN:
{
prevX=(int)event.getRawX();
prevY=(int)event.getRawY();
par.bottomMargin=-2*v.getHeight();
par.rightMargin=-2*v.getWidth();
v.setLayoutParams(par);
return true;
}
}
return false;
}
});
I am using drag and drop in a current project, where the various Views are placed within a RelativeLayout according to LayoutParams applied to them. Like you, I found that Views would 'shrink' when reaching the right or bottom of the ViewGroup container. It's probably quite obvious that this will happen, really, considering that during the measure and layout phases, the system is going to determine that a given View is suddenly going to have to have much smaller dimensions than you actually wish if it's still going to be able to fit into the parent when placed near the extremes.
A very simple solution I've done to get around that at the moment is to simply oversize my ViewGroup relative to the screen size.
Furthermore, you may decide that you don't actually want Views to appear partially off-screen, in which case you'd use some program logic to prevent the View objects' margins being set such that the Views are allowed to go off the parent container's boundary.
Another solution might be to override onMeasure() or similar to force the child View to force a larger size than the parent deems is available to it -- if that's possible -- to force the View to be placed there in the desired size, overlapping the edge. That's just an idea off the top of my head though and have not investigated it.

Categories

Resources