I have a FrameView containing a full-screen ImageView on top and a full-screen SurfaceView underneath. The ImageView starts out INVISIBLE while I display the SurfaceView. Now I set the ImageView to VISIBLE and want to update what is on the SurfaceView, unseen.
But the ImageView is not yet really visible. I have to wait until the ImageView is actually visible before messing with the SurfaceView. How is this done?
The only way I found was to wait 50ms (nothing less would do) before messing with the SurfaceView. Which happens to work reliably on my device, but is obviously a hack.
To be more specific: on the SurfaceView I am preparing a movie. Which makes the screen go black. I am trying to avoid the black by covering it with an image.
Any help appreciated!
You can use View.onVisibilityChanged().
Related
I'm building an app where I want to swipe images as though they were photos on a stack. In other words, if I swipe the top image I want it to animate moving in the direction of the swipe and have the next image underneath it visible the whole time. To accomplish this, I'm using a FrameLayout and two ImageView containers. I'm just alternating which one is on top. Meanwhile, as soon as a swipe occurs, the next image is loaded into the ImageView at the back using setBackground(drawable). My problem is that the ImageView at the back doesn't update it's image until I call bringToFront() on it, which means that as the top ImageView is animating, the image underneath is incorrect until the animation completes, at which point it abruptly changes to the correct image. I've tried calling invalidate() on the rear ImageView after setBackground(drawable) but this doesn't work. Anyone have any ideas on how I can get the image to update while it's behind?
UPDATE: Turns out I'm just not very on it today. I was updating the wrong ImageView and because the image loading was being done off the network, there was just enough lag to make me think it was happening after the animation completed.
Sounds to me like you wanna do something like an Image Slider.
There are great libraries existing for this purpose, this one for example:
https://github.com/daimajia/AndroidImageSlider
If you don't wanna use this, here are some tips:
Images on ImageViews are set with setImageDrawable(Drawable)
When your animation starts, set the new Image to your ImageView behind and slide the visible one away.
When the visible ImageViewhas slided away, set it's visibility to GONEand move it behind the second ImageView
Do this for every time a new image is loaded.
This should actually work.
You need a "ViewPager"
https://developer.android.com/training/animation/screen-slide.html
It has all the necessary handles to accommodate "N" number of images - also supports multiple swipe animations - default handlers - efficient memory management - prefetching - you are all in for a feast with this !!
Just make sure you get the "ImageView" in the layout of the "pages" you wish to develop on the "ViewPager".
I got a SurfaceView, in which I display a bitmap that is much larger than the actual area of the SurfaceView, so I have implemented a way for the user to slide their finger on the bitmap and move it up and down. When doing so, I would like to be able to display a vertical scroll bar, preferably the standard Android scroll bars, instead of drawing something custom.
The thing is, I would like my SurfaceView to stay the size of the screen, that is I don't want to scroll the SurfaceView itself, I just want to create the illusion that the user is scrolling the contents, and therefore display the scrollbars.
I tried setting android:scrollbars = "vertical" in the layout's XML, I tried mSurfaceView.setVerticalScrollBarEnabled(true); and I tried awakenScrollBars(); whenever the user touches the SurfaceView, however none of those displays the scrollbars.
So, is it possible to display the standard Android scrollbar on a SurfaceView?
short answer is: no!
everything that the SurfaceView ever draws on the screen is whatever you directly call to be drawn using the whole lockCanvas and unlockCanvasAndPost that you know about.
Putting those parameters in the XML make it possible for you to read them in Java via the AttributeSet in the constructor, but that's only for configuration, it won't drawn anything.
I would like to make a simple Android game where a large background image is displayed and some other images are displayed in specific locations over it, where the other images may be clickable.
Here's a quick sample image of what I'm talking about:
The user should be able to tap the soccer player or the moose (ah, the classic "soccer player moose problem"!)
How should I render this screen (which layouts and views?) so the user can interact with it and it will scale properly on different devices?
I would use a RelativeLayout.
You can set the you background image to the layout (fill_parent for height and width).
You can then put your ImageViews, containing your moose and soccer player down on the layout relative to the top or sides of the sceen, or relative to each other (making sure to specify "dp" units for everything). Set the backgrounds of your ImageViews to be transparent, and there won't be a bounding box problem (and/or you can also set your ImageViews alignment to be relative to each other, ensuring they don't overlap).
I think this is the simplest way to do this - it is then super easy to attach onClickListener to your ImageViews in your Activity, and you are done.
This type of layout will work the same on all devices and screen sizes.
There are some small gotcha's with RelativeLayouts, but they are pretty simple once you get into them, and provide fast rendering (since the view hierarchy is usually shallow). Good Luck.
ImageView for the clickable elements seems like a fine choice to me. For the background I would just set your image as the background of the parent layout i.e. RelativeLayout
SurfaceView for the whole thing (with your field as a background) and regular *ImageView*s for added elements. You can easily recover the click coordinates from the SurfaceView and thus know what element has been touched.
SurfaceView might offer you additional possibilities anyway.
For most images, I'd use an ImageView for each one, like FoamyGuy said.
If they're close enough for overlapping bounding boxes to be an issue, you can still use an ImageView for each, but with a variation of this answer, testing alpha for each ImageView in range.
I would agree with both FoamyGuy and Booger that if your only goal is to place static images onto the screen that do something when you click them, RelativeLayout and ImageViews all the way.
But...
If you are looking to randomly spawn multiple images onto the screen in intervals and have them move around for the player to interact with while explosions are going off and maidens are being kidnapped, you should look into SurfaceView, Canvas, Drawable, TouchEvents, and FrameBuffers.
Is it possible to draw an image over another view (like a button) and still have the view work normally? The user would still be able to click on the button even though there is another image on top of it. I want to draw some mostly transparent pngs over my layout for lighting effects, but I want to make sure everything will still work correctly.
Try using a RelativeLayout with an ImageView on top of the widget(s) in your app. See this question for a quick example.
I am trying to play a videoview on top of another video view. The first video view is paused, while the second is playing. It appears to work but no second video appears on the screen (though I hear the audio and see the controls that would normally appear on top). I am assuming this is some sort of order issue. Any thoughts. By the way, I have no problem displaying other views on top of the main video view and having the video fill the background.
That won't work - the VideoView is special in the sense that it 'punches' a hole in the normal Views to allow direct access to the display pixels (or, in android terms, the 'Surface' - VideoView is a subclass of SurfaceView). You cannot layer two SurfaceViews on top of eachother - the first one that grabs the pixels (the Surface) will 'own' it. (see SurfaceHolder.Callback.surfaceCreated() / surfaceDestroyed())
Other Views on top of a SurfaceView do work, because the framework will compose the display bits of normal Views on top of the Surface. It cannot do that with another VideoView (i.e. a SurfaceView) because there is nothing to compose.
<VideoView android:id="#+id/videoView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<VideoView android:id="#+id/videoView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
when videoView2 starts playing setvisibilty of videoView1 invisible.
then you can make it visible when you need.
Use Thread to control both video
I don't know if this is helpful at the moment, but I managed to get something similar to what you want...
I needed to nest a VideoView on top of a SurfaceView; as long as they don't overlap 100% it can work. (what i mean is, my surfaceview is the whole screen and videoview is just a small portion of the screen)
The thing is - since you can't compose SurfaceViews, the first one to grab the pixels is the one that will be shown. Intuitiveness will drive you to Z-order your prioritized view AFTER the less-important one in the XML - but as I've said previously, the first one to grab the pixels stays, so make sure you define the smaller view FIRST, and then overlay it with the bigger one.
This will result in such behaviour that the smaller (in my case preview view) acquires the said X * Y pixels, and then the 'background' surfaceview (which is supposed to be on top of it according to the XML) takes up the rest and ignores the smaller surface.
I'm not too sure about handling events from those two though as I only have to play streams in those two views and not react to any kind of clicks/events generated by those two components, but it might be expected that if you followed this route - the bigger view will intercept all clicks made in the smaller view area (because it's on top according to the XML) so maybe you have to programatically move it on top as well upon creation.
Hope it helps.
EDIT:
Although... it like it just works once. It's a work in progress really. Upon returning from any activity, there's nothing i can do to prevent the bigger view claiming everything :/
you can add videoview a on top videoview b,like this,
parentview.removeview(a);
parentview.removviewe(b);
parentview.addview(a);
parentview.addview(b);
parentview.invalidate();
Ti's work for me. I hope it can helps.