Invisible SurfaceView makes its parent black - android

I have a problem using a SurfaceView inside an activity layout. This is the piece of XML:
<LinearLayout...
android:background="#drawable/background_image">
...
<RelativeLayout
android:id="#+id/game_viewcontainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.85">
<!-- SurfaceView will be placed here -->
</RelativeLayout>
</LinearLayout>
As you can see, the SurfaceView (actually a subclass of it) is not directly placed into the XML, but I put it later from the code, this way:
In the activity's onCreate() I instantiate the SurfaceView, setting it to INVISIBLE. I don't want to show it now.
Few lines after I call addView() to place the surface inside game_viewcontainer
The activity is rendered.
After few seconds I switch the surface to VISIBLE.
The problem is that this sequence works on some testing devices with Android 4+, but it introduces an issue in Android 2.2: between the 2nd and 4th step the game_viewcontainer is totally black (it doesn't show background_image). Then, after setting the SurfaceView to VISIBLE, the problem disappears.
Why this behavior?

Related

Rotated ListFragment disappears when empty view displayed after Filter

Just to be clear, we're talking about an XML rotated view here, not the effects of rotating the device. I have a SlidingDrawer that contains a ListFragment. The ListFragment implements the Filterable interface so that users can search its contents by providing a string input through an EditText.
The relevant layout is included below. Because the SlidingDrawer class was deprecated in API 17, the source code was copied over an accessed via a local class. That's why the name of that view looks like a custom class when really it's not.
<com.example.echo.views.SlidingDrawer
android:id="#+id/left_sliding_drawer"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:handle="#+id/left_handle"
android:orientation="horizontal"
android:content="#+id/people_fragment_container"
android:rotation="180">
<LinearLayout
android:id="#id/left_handle"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/people_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/people_map_tab_grey"
android:rotation="180"
android:contentDescription="#string/people_tab"/>
</LinearLayout>
<FrameLayout
android:id="#+id/people_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.example.echo.views.SlidingDrawer>
What happens is, when the users provides input and filters the list such that there are no matching results, i.e., the ListView is empty and size is 0, the entire SlidingDrawer disappears.
Some things I've noticed in trying to fix this:
I am pretty sure this is related to displaying the empty view and/or whatever layout change occurs when it is displayed. If I simply do not set an empty view for the ListFragment the issue does not occur.
I am also pretty sure the effects are related to the fact that the SlidingDrawer is being rotated by 180 degrees since, if I remove the rotation attribute, the issue also does not occur. However, because SlidingDrawer in its default state only opened right to left, this drawer applies the XML attribute android:rotation="180" to flip the view so that it can be opened left to right. This must remain since there is other stuff on the right side of the screen that cannot be moved.
I'm not sure what is making the view disappear or where to start fixing it. I've trying fixing the child views' sizes by overriding onMeasure, onSizeChanged, and onLayout but cannot find anything that solves the issue.
Any ideas are appreciated.

Android how to ignore auto resizing when keyboard pops up?

let's say I have a view that is made up of 2 layers -> top layer and bottom layer. I place them both in a frame layout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- bottom layer -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/some_image_you_shouldnt_shrink"/>
<!-- top layer -->
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/somewhat_transparent"/>
</FrameLayout>
now, presumably, when i tap on the editText, the keyboard will pop up, and shrink the size of the edit text. However, it seems that the bottom layer is ALSO getting resized. How do i prevent this bottom layer from getting resized?
Note: the framelayout is in a fragment, and the activity that holds this fragment must declare android:windowSoftInputMode="adjustResize".
EDIT*********
Just to clarify, i want the editText layer to adjust as high as the keyboard needs to. however, i don't want the image behind it to adjust at all
i only have 1 activity that handles these similar types of fragments.
You can't prevent a single view from resizing if you set android:windowSoftInputMode="adjustResize". But if you just want to set a non-resizing background, there is a work-around. Instead of setting the background image in the ImageView through XML, add this in your onCreate() method
getWindow().setBackgroundDrawableResource(R.drawable.some_image_you_shouldnt_shrink);
try this in the manifest
android:windowSoftInputMode="stateVisible|adjustPan"

Android camera preview is always shown above other SurfaceViews in FrameLayout

In Android 2.3 application I used to support two cameras: one built-in and onу externally MJPG-streamed using Wi-Fi. The built-in camera must be recording video all the time and a user must have the ability to switch view between those. So, each camera had a dedicated SurfaceView to draw on. As the last child added to a FrameLayout has a higher Z-order, I programatically add the required camera view to a FrameLayout last to make it visible. I can't skip adding built-in camera since it can't record video without the preview display.
This scheme no longer works with Android 4: the built-in camera preview is always shown in spite of being added first or last. I played with 'setVisibility' methods on views and noticed that if one of views is set to be invisible (or gone) then none of them is showed at all. ViewGroup's 'bringChildToFront' method had no effect as well.
So, is there some workaround to make this work on Android 4? And I know that having multiple SurfaceViews is considered bad. Some code follows.
FrameLayout:
<FrameLayout android:id="#id/data"
android:layout_width="fill_parent" android:layout_height="fill_parent"/>
Code that populates the layout (no longer works on Android 4):
private void setCorrectView() {
data.removeAllViews();
List<Recorder> others = recorders.getOthers();
for (Recorder other : others) {
addToTheView(other);
}
addToTheView(recorders.getCurrent());
}
private void addToTheView(Recorder recorder) {
View view = recorder.getView(this); // get recorder's surface view
data.addView(view);
}
The same effect if I use FrameLayouts from XML:
<FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#id/data"
android:layout_width="fill_parent" android:layout_height="fill_parent"/>
<FrameLayout
android:id="#+id/data_invisible"
android:layout_width="fill_parent" android:layout_height="fill_parent"/>
</FrameLayout>
Wherever I put built-in camera's surface view - it's always shown. Looks like internal camera's preview is now always on top in Android 4.
Answering to myself. To make this work I set the views' visibility to View.VISIBLE before starting the camera and set it to View.INVISIBLE after. This link may be helpful.

How to use LayoutInflater / ViewStub for an overlay

As I am actually not very confident with programatically changing Views, I have following problem:
At the first start of my app, I want to have an overlay for the main screen, that tells the user to have a look at the settings, as there are two critical options the user has to configure.
I don't want to use an AlertDialog and rather not use a wizard. So, I decided to take an approach similar to Go SMS and create an overlay at the first start. The mockup I created looks like this:
Normal menu:
First start:
So these are the problems I have:
Like I said, I don't want to use a screenshot overlaying on first start, as this would take too much space and would not be language and screen independent.
I would have the circle as an png, but I don't know how exactly put it over the image
The same problem with the text
And finally I want to put a semi-transparent white over the app. It does not necessarily need the hole for the icon, though it would be nice.
In case you need the Layout Source, you can get it at pastebin
So, I just need to get a start here, if it is better to use LayoutInflater or ViewStub and how to realize it, as I have absolutely no experience with it...
Thanks!
/edit: I uploaded a new, more well-arranged layout.
I have faced a similar problem, I client wanted a walkthrough of the application, where the entire screen had to become whiter (as they said: "transparent"), except for the button being explained by an overlay speech-bubble.
Fortunately for you, your layout is not nearly as complicated as the one I had to work with :)
Now, you can get the transparency-effect in two ways, either have a white background and call all the views setAlpha() methods, or you can create a half-transparent white overlay.
If you go with the overlay, you'll have to find a way to display the opaque buttons through the overlay. This can get a bit complicated.
If you go with the first option, you can just setAlpha(1) on the opaque view to get it to show up.
The setAlpha() method is only available from api version 11+, so if you target an earlier version, you might have to do it in a slightly more complicated way.
Example of setting alpha on views pre-honeycomb:
Layout for your buttons (make them however you want, just make them similar so you can loop through them):
<LinearLayout
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:tag="image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/tile"/>
<TextView
android:tag="text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF000000"
android:text="button1"/>
</LinearLayout>
In your program, when you are want to make the buttons transparent:
LinearLayout l = (LinearLayout) findViewById(R.id.button1);
((ImageView)l.findViewWithTag("image")).setAlpha(0x7F);
((TextView)l.findViewWithTag("text")).setTextColor(0x7F000000);
When you have decided on how you want to create the transparency effect, you will have to decide on how to display the overlay-text/bubble. You'll most likely want to put this in a separate layer on top of your entire layout, to make sure that it is not affected by your new view.
One way to achieve this is by changing your root layout element to a FrameLayout, and then creating/displaying in this. e.g:
<FrameLayout background="#FFFF"> <!-- white background, just in case -->
<LinearLayout>
<!-- the rest of your layout -->
</LinearLayout>
<LinearLayout visibility="gone"> <!-- this will be your overlay view -->
<ImageView /> <!-- the arrow/ring -->
<TextView /> <!-- the description -->
</LinearLayout>
</FrameLayout>
When the introduction is displayed, you set the position of the hidden overlay-view to the position of the table item to be explained, change the text to an appropriate string/resource and display the view.
When the introduction is over, you reset the alpha values of all buttons, and set the visibility of the overlay to gone again.
Since I don't have much experience with ViewStub, I would do it with LayoutInflater.
First of all, you need to have a second layout loaded on top of your current layout. The easiest is to have a FrameLayout, which has as one child your current view, and the dynamically you load the second child on the first start. When you load a content view in an Activity, it will be attached to some already created views (some DecorView, a FrameLayout, etc). So you can either re-use the existing FrameLayout, or you can create a new one.
I would vote for the second solution, since it's more stable (I just mentioned the other possibility in case you want to minimize the number of layers).
So, as a first step, wrap your current layout inside a FrameLayout, and give it an id, let's say "#id/root".
Then, in the onCreate method, you can have something like this:
setContentView(R.layout.main);
if (isFirstRun()) {
ViewGroup parent = (ViewGroup)findViewById(R.id.root); // locate the FrameLayout
LayoutInflater li = LayoutInflater.from(this); // get an instance of LayoutInflater
li.inflate(R.layout.overlay, parent);
}
So far you will have the overlay loaded. Now it's up to you to define the overlay.
To make the whitening effect, just set the following attribute on the root view in your overlay.xml layout:
android:background="#40ffffff"
To position the circle, first you need to find it's location. You can use the View.getLocationOnScreen to get the absolute coordinate of the icon (below the circle) on the screen. Then you can have two options:
either create a custom view (for the overlay) and manually draw the circle at the given location
or add the circle using an ImageView and adjust the left and top margins based on the coordinates

How can I to make surfaceview invisible in Android?

in my app i am using a media player with a seek bar. The seek bar of works along with a surface view. Now my problem is the surface view appears at a corner of my layout which appears to be a black screen. How can i make the surface view to be an invisible. Following is the image of my layout,
You can do that by setting the visibility in the code:
surfaceView.setVisibility(View.GONE) or surfaceView.setVisibility(View.INVISIBLE).
And you can do the same by setting it in the XML:
<SurfaceView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"/>
GONE is used if you want it to be completely gone and ignored by the rest of the layout. INVISIBLE is used if you only want to change the visibility.
you can use surfaceView.setVisibility*(View.INVISIBLE);

Categories

Resources