clickable image inside canvas - android

I have create a canvas in android and inside that i have multiple bitmap images.not i want to make these images click able.
I have tried following things so far..
I tried to add bitmap in image view as imageview has a setOnClickListner
but i think ImageView can't be added into Canvas , so i dropped this idea. because even Bitmap itself has no click events.

If you want to use Canvas, keep in mind that it is a low level drawing mechanism.
Therefore, you need to implement the click logic yourself.
Catch the coordinates of any incoming TouchEvent.
If the TouchEvent is a "touch down" (finger pressed) or "touch up" (finger released), depending on your choice, consider it to be a click.
Compare the click event coordinates to every attached image's bounding box to find which image was touched. Take the z-index into account in case of overlap.
Trigger an onClickListener.
You also have to keep the coordinates of all images and the corresponding onClickListeners somewhere in memory.
Other solution:
Use a Layout, possibly a RelativeLayout, in which you add the ImageViews as children.

I believe you're asking for something like that:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background"
android:orientation="vertical" >
<ImageView
android:id="#+id/clickable_image"
android:src="#drawable/ic_image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="true"
/>
</LinearLayout>
Now you have your background "setting the whole view as a wallpaper" in your own words, and then you have your image, which is clickable. In your code you implement onClickListener and attach it to your ImageView and it will do whatever you want it to do.

Related

android click image to zoom in (larger than screen) and move around, and click again to go back to default size

I've done my searches extensively for sure, but I haven't come across exactly what I'm looking for. As such, I haven't any code to show for what I want to do. I want to know if it's possible, first of all, and then get a lead on how to implement such an action.
To keep my app simple, I'd really like to avoid starting a new activity, which seems to be involved in many of the "solutions" that I've seen.
My setup isn't anything special, just a layout with some textviews, buttons, and an image that's about as large as the screen.
I want the user to be able to click the image, and the image will "zoom" or "enlarge" to about 4-5x the size, obviously much of the image will then be off screen. Then, the user should be able to drag the image around to view the entire image as they wish. When they're done looking at the image, they should be able to click to go back to the original size.
I'm sure this will warrant a separate image for each size (one for the original, and a larger more detailed image for the enlarged version). Though, the simpler the better. If I can maintain one larger detailed image and scale it down for the standard view before it's clicked, that'd be great.
I'm assuming they'll be a click listener on the image, but I'm not sure how to do what I want without starting a new activity entirely, then upon clicking again, going back to the original activity. Can it be done in the same activity?
Thanks in advance.
EDIT:
I just had an idea. I could have the larger image in a relative view and make it invisible/gone, then make it visible upon click of the original/main image. Clicking the large image will make itself invisible/gone again. But, assuming this works, I do'nt konw how to set the action of dragging it around and boundaries to make sure you can't drag it outside of the screen entirely.
i have use this library in my project for Zooming images and its very simple to use its helps you ...
https://github.com/chrisbanes/PhotoView
JAVA:
PhotoView mImageView;
PhotoViewAttacher mAttacher;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Any implementation of ImageView can be used!
mImageView = (PhotoView) findViewById(R.id.iv_photo);
// Set the Drawable displayed
Drawable bitmap = getResources().getDrawable(R.drawable.wallpaper);
mImageView.setImageDrawable(bitmap);
// Attach a PhotoViewAttacher, which takes care of all of the zooming functionality.
mAttacher = new PhotoViewAttacher(mImageView);
}
// If you later call mImageView.setImageDrawable/setImageBitmap/setImageResource/etc then you just need to call
attacher.update();
XML:
<uk.co.senab.photoview.PhotoView
android:id="#+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp" />
In hopes that this helps someone else and that my solution will suffice in fixing someone else's issue, I'm going to answer my own question with what I found to be a good fix.
To keep it as simple as possible (as it seems that implementing such a feature requires more extensive work that I feel should be necessary), I used the method of toggling hidden/invisible views.
<FrameLayout>
<!--Main Activity-->
<LinearLayout>
<!--Primary Image-->
<ImageView
android:onClick="makeZoomVisible"/>
</LinearLayout>
<!--ScrollView Holder for Enlarged Image-->
<HorizontalScrollView
android:visibility="gone">
<!--Enlarged Image-->
<ImageView
android:onClick="makeZoomInvisible"/>
</HorizontalScrollView>
</FrameLayout>
The base layout is a Frame layout, which allows me to place the Enlarged Image holder (horizontal scroll view) on top of everything else since it comes after the main activity view (linear layout).
Once the primary image is clicked, it calls the method "makeZoomVisible", which as you may guess, toggles the visibility for the horizontal scroll view which holds the enlarged image. The image is scaled up to as large as the height of the screen allows. This works for me because my app is portrait only, and allows the image to scale up approximately 4x the size (a 2x2 of the original image size, just for comparison). Since the image maxes out at the height of the screen, there's no need to scroll/drag up and down. But the horizontal scroll allows the image to be moved side to side to view the whole image.
Clicking the enlarged image calls the method "makeZoomInvisible" which toggles its own visibility, clearing it away and allowing the user to see the main layout of the activity again.
This is the best option for me as a new Android app developer because of its simplicity. To refrain from switching activities, saving/pausing the current activity, implementing 3rd party libraries to include a horizonal+vertical scroll, or pinch zoom and drag features I'm able to achieve what I need for my app.
Hopefully this helps someone else out that may be looking for a simple solution.
I know you decided to implement simple transition yourself without using 3rd party libs. But if someone else is looking for more complex solution, I can suggest to try this library, it allows zooming from i.e. RecyclerView items to ViewPager with animation and includes zoom/pan/rotation features as well.
(Note, I'm the developer of this library)
Simple usage example:
Add regular ImageView and GestureImageView into layout:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_small"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.alexvasilkov.gestures.views.GestureImageView
android:id="#+id/image_full"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Set same image into both views:
smallImage.setImageDrawable(...);
fullImage.setImageDrawable(...);
Start animation:
fullImage.getPositionAnimator().enter(smallImage, true);
For more info see documentation and sample project.
A great way to do this would be to use a custom ImageView to handle the zooming and dragging of the image that way you can keep it in the same layout without having to start a new activity.
You should check out the TouchImageView library. It contains a custom ImageView that allows pinch zoom, double tap to zoom, dragging, and the ability to manually set the zoom of the image.
If don't want to include the full library a simple way to add this functionality would be to copy the TouchImageView java class into a package in your app (eg com.myapp.views).
Then in your xml layout instead of using:
<ImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_image" />
Change your image to use the path of the custom view class:
<com.myapp.views.TouchImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_image" />

Prevent ImageView from receiving touch events when scrolling

I'm making an app with lots of ImageViews and I needed to attach a touch listener in some of them. While doing this, I encountered a problem. If the pointer was held down at the location where the ImageView with touch listeners attached to it and was about to produce a scrolling event, there seems a fighting scene between the Views and the ScrollView in w/c where the event was actually occured and in w/c the event is supposed to belong. The screen scrolls in a fast rate then return where the first pointer was touched down, so it means it is an unwanted behavior.
Setting an onTouchListener in the ImageView makes the scrolling uneasy and unwanted, how do I prevent ImageView from receiving touch events when scrolling?
Some of the codes
Layout: act_map_view.xml
<?xml version="1.0" encoding="utf-8"?>
<com.nkraft.mobiletomblocator.CustomVScroll
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/vScroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" >
<com.nkraft.mobiletomblocator.CustomHScroll
android:id="#+id/hScroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none" >
<com.nkraft.mobiletomblocator.CustomGridLayout
android:id="#+id/map_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</com.nkraft.mobiletomblocator.CustomGridLayout>
</com.nkraft.mobiletomblocator.CustomHScroll>
</com.nkraft.mobiletomblocator.CustomVScroll>
Notes:
The GridLayout is populated with ImageViews at runtime.
I customized my horizontal and vertical ScrollView so that I can scroll in both directions concurrently i.e diagonal scrolling
From the notes I've mention, I figured a clue from the problem I'm currently facing. I think this issue had been thought before the standard android's scrollbar was implemented. The main reason this occurs to me is that I extended the class of the scrollbars and totally replacing the default behavior of it. So for me to achieve what I want (the scrollbar with diagonal scrolling) I follow this post and replace both my vertical and horizontal scrollview with this TwoDScrollView, also thanks for this post directing me to it.

Android bringToFront GridView Issue

I'm developing an app which contains an image at the upper half of the screen and a gridview in the half below, like this:
<de.test.gridview.Image
android:id="#+id/image_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:fadingEdgeLength="0dp"
android:scrollbars="none"
android:visibility="gone" />
<de.test.gridview.DraggableGridView
android:id="#+id/grid_view1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/topnews_container"
android:background="#FFF"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="none"
android:tag="grid_view_tag" >
</de.test.gridview.DraggableGridView>
The Image is set to visibility=gone and set to visible in the code manually later on.
When I now drag on of the childs of the gridview I cant be able to drag them over the image in the upper half of the screen. They are always behind the image, but never in front of it. I've tried to use
gridView.bringToFront()
and also within the gridView I tried this function. I also tried this on the children of the gridview with gridView.bringChildToFront(child). But nothing worked.
Does anybody have an idea?
I guess view with property set to View.GONE is not operational via bringToFront(). So I believe the following will work (if you are trying to bring the grid to the front/top of z):
gridView.setVisibility(View.INVISIBLE);
gridView.bringToFront();
But its looks like you want to bring imageView to the front (making gridView behind instead of front). If so you need to:
imageView.setVisibility(View.INVISIBLE);
imageView.bringToFront();

redundant onDraw() calls in FrameLayout

I have the following layout structure in my xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<MyEntireView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</MyEntireView>
<FrameLayout
android:id="#+id/focusedlayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<MyDetailedView
android:id="#+id/focus"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</MyDetailedView>
</FrameLayout>
</FrameLayout>
MyEntireView is a map (a Drawable) and MyDetailedView pops up on top of it upon onTouch() and contains only a certain piece of the whole map (also Drawable) that displays in greater detail the area which the user touched on the entire map in MyEntireView.
When MyDetailedView is shown - i.e. its setVisibility(View.VISIBLE) - there appear some transparent shapes (also some Bitmaps) on top and are redrawn regularly (e.g., 1 sec interval). The shapes are added dynamically as children of the #+id/focusedlayout as there is always a different number of them and their position is relevant to the detailed map picture.
And the problem is that each single update is processed multiple times. Each time a shape updates, then MyEntireView's onDraw() is called, MyDetailedView's onDraw() is called, and then these two are called again. And only after this the shape itself is invalidated.
As a result, this behaviour makes the shape flicker, since MyDetailedView redraws and hides the shape for 10ms or so.
I must probably be overlooking some simple logic, but I really can't get if there is a way to force only one View of a ViewGroup invalidate().
Or maybe there is an alternate structure/layout that I could use to fit my purpose?
Thanks a lot!
P.S.
The entire code is quite big to put here but I'm willing to insert any pieces upon request

Overlapping Views in Android

Is it possible to have overlapping views in Android? I would like to have an ImageView with a transparent png in the front and another view in the background.
edit:
This is what I have at the moment, the problem is that the image in the imageView is not transparent, the parts that should be transparent are just black.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/gallerylayout"
>
<Gallery android:id="#+id/overview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView android:id="#+id/navigmaske"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="#drawable/navigmask"
/>
</RelativeLayout>
edit:
I got it to work, it was a theme file from another programmer on the team.
Just changed this
<item name="android:background">#FF000000</item>
to this
<item name="android:background">#00000000</item>
Android handles transparency across views and drawables (including PNG images) natively, so the scenario you describe (a partially transparent ImageView in front of a Gallery) is certainly possible.
If you're having problems it may be related to either the layout or your image. I've replicated the layout you describe and successfully achieved the effect you're after. Here's the exact layout I used.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gallerylayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Gallery
android:id="#+id/overview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/navigmaske"
android:background="#0000"
android:src="#drawable/navigmask"
android:scaleType="fitXY"
android:layout_alignTop="#id/overview"
android:layout_alignBottom="#id/overview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
Note that I've changed the parent RelativeLayout to a height and width of fill_parent as is generally what you want for a main Activity. Then I've aligned the top and bottom of the ImageView to the top and bottom of the Gallery to ensure it's centered in front of it.
I've also explicitly set the background of the ImageView to be transparent.
As for the image drawable itself, if you put the PNG file somewhere for me to look at I can use it in my project and see if it's responsible.
Also, take a look at FrameLayout, that's how the Camera's Gallery application implements the Zoom buttons overlay.
If you want to add your custom Overlay screen on Layout, you can create a Custom Linear Layout and get control of drawing and key events. You can my tutorial- Overlay on Android Layout-
http://prasanta-paul.blogspot.com/2010/08/overlay-on-android-layout.html
The simples way arround is to put -40dp margin at the buttom of the top imageview
A visible gallery changes visibility which is how you get the gallery over other view overlaps. the Home sample app has some good examples of this technique.
Now with Jetpack Compose in android, you should use Box for overlapping views.
Example.
Box(modifier = Modifier.fillMaxWidth().fillMaxHeight()){
RecipesList(viewModel.recipes.value)
Snackbar()
}
Here RecipesList and Snackbar are composabes positioned one on top of the other in the composition order
Check out this for Jetpack Compose samples - https://androidlearnersite.wordpress.com/2021/08/03/jetpack-compose-1-0-0-sample-codes/
Yes, that is possible. The challenge, however, is to do their layout properly. The easiest way to do it would be to have an AbsoluteLayout and then put the two images where you want them to be. You don't need to do anything special for the transparent png except having it added later to the layout.

Categories

Resources