Can you overlay a view on top of everything in android?
In iPhone I would get the new view set its frame.origin to (0,0) and its width and height to the width and height of self.view. Adding it to self.view would then cause it to act as an overlay, covering the content behind (or if it had a transparent background then showing the view behind).
Is there a similar technique in android? I realise that the views are slightly different (there are three types (or more...) relativelayout, linearlayout and framelayout) but is there any way to just overlay a view on top of everything indiscriminately?
Simply use RelativeLayout or FrameLayout. The last child view will overlay everything else.
Android supports a pattern which Cocoa Touch SDK doesn't: Layout management.
Layout for iPhone means to position everything absolute (besides some strech factors). Layout in android means that children will be placed in relation to eachother.
Example (second EditText will completely cover the first one):
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/root_view">
<EditText
android:layout_width="fill_parent"
android:id="#+id/editText1"
android:layout_height="fill_parent">
</EditText>
<EditText
android:layout_width="fill_parent"
android:id="#+id/editText2"
android:layout_height="fill_parent">
<requestFocus></requestFocus>
</EditText>
</FrameLayout>
FrameLayout is some kind of view stack. Made for special cases.
RelativeLayout is pretty powerful. You can define rules like View A has to align parent layout bottom, View B has to align A bottom to top, etc
Update based on comment
Usually you set the content with setContentView(R.layout.your_layout) in onCreate (it will inflate the layout for you). You can do that manually and call setContentView(inflatedView), there's no difference.
The view itself might be a single view (like TextView) or a complex layout hierarchy (nested layouts, since all layouts are views themselves).
After calling setContentView your activity knows what its content looks like and you can use (FrameLayout) findViewById(R.id.root_view) to retrieve any view int this hierarchy (General pattern (ClassOfTheViewWithThisId) findViewById(R.id.declared_id_of_view)).
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id = "#+id/Everything"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- other actual layout stuff here EVERYTHING HERE -->
</LinearLayout>
<LinearLayout
android:id="#+id/overlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right" >
</LinearLayout>
Now any view you add under LinearLayout with android:id = "#+id/overlay" will appear as overlay with gravity = right on Linear Layout with android:id="#+id/Everything"
You can use bringToFront:
View view=findViewById(R.id.btnStartGame);
view.bringToFront();
The best way is ViewOverlay , You can add any drawable as overlay to any view as its overlay since Android JellyBeanMR2(Api 18).
Add mMyDrawable to mMyView as its overlay:
mMyDrawable.setBounds(0, 0, mMyView.getMeasuredWidth(), mMyView.getMeasuredHeight())
mMyView.getOverlay().add(mMyDrawable)
I have just made a solution for it. I made a library for this to do that in a reusable way that's why you don't need to recode in your XML. Here is documentation on how to use it in Java and Kotlin. First, initialize it from an activity from where you want to show the overlay-
AppWaterMarkBuilder.doConfigure()
.setAppCompatActivity(MainActivity.this)
.setWatermarkProperty(R.layout.layout_water_mark)
.showWatermarkAfterConfig();
Then you can hide and show it from anywhere in your app -
/* For hiding the watermark*/
AppWaterMarkBuilder.hideWatermark()
/* For showing the watermark*/
AppWaterMarkBuilder.showWatermark()
Gif preview -
I have tried the awnsers before but this did not work.
Now I jsut used a LinearLayout instead of a TextureView, now it is working without any problem. Hope it helps some others who have the same problem. :)
view = (LinearLayout) findViewById(R.id.view); //this is initialized in the constructor
openWindowOnButtonClick();
public void openWindowOnButtonClick()
{
view.setAlpha((float)0.5);
FloatingActionButton fb = (FloatingActionButton) findViewById(R.id.floatingActionButton);
final InputMethodManager keyboard = (InputMethodManager) getSystemService(getBaseContext().INPUT_METHOD_SERVICE);
fb.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// check if the Overlay should be visible. If this value is false, it is not shown -> show it.
if(view.getVisibility() == View.INVISIBLE)
{
view.setVisibility(View.VISIBLE);
keyboard.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
Log.d("Overlay", "Klick");
}
else if(view.getVisibility() == View.VISIBLE)
{
view.setVisibility(View.INVISIBLE);
keyboard.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
bringToFront() is super easy for programmatic adjustments, as stated above. I had some trouble getting that to work with button z order because of stateListAnimator. If you end up needing to programmatically adjust view overlays, and those views happen to be buttons, make sure to set stateListAnimator to null in your xml layout file. stateListAnimator is android's under-the-hood process to adjust translationZ of buttons when they are clicked, so the button that is clicked ends up visible on top. This is not always what you want... for full Z order control, do this:
Related
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:EMVideoView="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/MUVCastleRock">
<com.devbrackets.android.exomedia.ui.widget.EMVideoView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
EMVideoView:useDefaultControls="true" />
How do I change the color of the default controls (where you would see the play button)? I don't want to change the background behind the video, but instead the play bar. This is because my background is grey and so I want to change the color so that the bar is more visible.
EDIT:
#Shank suggested that I replace the images of the buttons in /exomedia/ui/widget/VideoControls.java
Although, I wasn't trying to change the images of these buttons, analyzing this class lead to my answer.
There are several functions within this class to change the settings of the default video controls.
You can set a title, description, subtitle, change out the button images (as Shank suggested), and solve my particular problem by changing the characteristics of the containers that contain the video controls (named controlsContainer).
The default container is initialized in retrieveViews() by the line:
controlsContainer = (ViewGroup) findViewById(R.id.exomedia_controls_interactive_container);
Using this, I simply called this reference from my EMVideoView and changed the color as appropriate:
emVideoView = (EMVideoView) myView.findViewById(R.id.video_view);
ViewGroup textContainer = (ViewGroup) emVideoView.findViewById(R.id.exomedia_controls_interactive_container);
textContainer.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.myColor));
Other useful methods that I discovered were as such:
emVideoView.getVideoControls().setTitle("title");
emVideoView.getVideoControls().setDescription("description");
emVideoView.getVideoControls().setSubTitle("sub");
emVideoView.getVideoControls().setPlayPauseImages(R.drawable.logo,R.mipmap.ic_launcher);
please see: http://i.imgur.com/iwikd69.png (the single "lorem" is a subtitle)
I am using the v7.21 appcompat library. I'd like to set a title to a Toolbar and if its too long then it should show as it does now (upper example in the image attached), only 1 line and it ends with ... if it doesnt fit. However I want the toolbar to expand (and then collapse respectively) onClick (possibly animated somehow) and show the full title (lower example)
Now I miss a few things here:
I dont see any method which would tell me if the title fits or not. (getSupportActionBar().isTitleTruncated() returns false even if the title doesn't fit, but maybe this is not the method I need, its not even a method of the Toolbar's class)
I can't seem to set the Toolbar's height programatically (even if i could, animating it would be a pain even more because I am targeting >=api15)
Is it possible to execute what I want or should I find a different solution?
Thanks
create custom toolbar
here is the example
/**
* Create the Action Bar and set the Custom View to it.
* Set content insets absolute (0,0) to hide the bottom margin for Action Bar.
*
*/
public void initializeAppToolbar()
{
actionbar = getSupportActionBar();
actionbar.setDisplayShowHomeEnabled(false);
actionbar.setDisplayShowCustomEnabled(true);
actionbar.setDisplayShowTitleEnabled(false);
actionbarView = getLayoutInflater().inflate(R.layout.custom_actionbar,null);
ActionBar.LayoutParams layoutParams = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,ActionBar.LayoutParams.MATCH_PARENT);
actionbar.setCustomView(actionbarView, layoutParams);
Toolbar parent = (Toolbar) actionbarView.getParent();
parent.setContentInsetsAbsolute(0, 0);
parent.setBackgroundResource(R.drawable.top_nav);
toolbar_title = (TextView)actionbarView.findViewById(R.id.toolbar_title);
// set click listener on toolbar_title.. and perform expand and collapse
// need to check this condition for lollipop and greater version
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(getResources().getColor(R.color.statusBarDark));
}
}
here is the custom_actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/top_nav"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Profile"
android:textColor="#android:color/white"
android:textStyle="normal"
android:textSize="24sp" />
I am trying to set a custom view in an ActionBar. I am using the support.v7 ActionBar - min API is 9. For some odd reason, I cannot get the custom view to appear in the ActionBar. Am I missing something painfully obvious? Any help appreciated.
Here is the layout I am inflating:
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="flsfjkelsjek"
android:background="#color/black"
android:textColor="#color/white"
/>
...Very simple, just a TextView for testing.
Here is the code to set this view as my custom ActionBar view:
TextView customView = (TextView) myInflater.inflate(R.layout.my_test_textview, null);
myActionBar.setDisplayShowTitleEnabled(false);
myActionBar.setDisplayHomeAsUpEnabled(true);
myActionBar.setDisplayShowCustomEnabled(true);
myActionBar.setCustomView(customView, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
Again, very simple and straightforward. I have tried many different varations on this, such as:
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_SHOW_TITLE);
and have even tried that line along with all of the above. I've also tried with a TextView just created on the fly, rather than inflating one.
The custom view simply doesn't appear. When I check the value of
myActionBar.getCustomView()
it returns my TextView. However, the width of that TextView is 0. Does anyone have any idea why the CustomView is not showing up?
I'm a relative beginner with Java and I'm still struggling somewhat with views. I've not had much success with searching through other posts or on-line tutorials. I won't post any code for this because I suspect many of you will know what's going on.
I have a canvas that allows me to draw lines on the screen with my finger, etc. I've got it working fine. My next task is to use a command button to save it as an image. The canvas covers the whole screen so the button I inserted on to the layout (in activity_main.xml) can't be seen.
My specific question is do I deal with the size of the canvas and access to the command button through a method(s) in the DrawView.java class or in the XML file in layout? Links to any good tutorials would be great. Thanks.
Use FrameLayout to show it overlappingly
In the XML the button would come below your View whose Canvas you are drawing on.
Frame Layout Example
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#D6FFD6"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:src="#drawable/android"
android:scaleType="fitCenter"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
<TextView
android:text="learnandroideasily.blogspot.com"
android:textSize="30sp"
android:textStyle="bold"
android:textColor="#003399"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:gravity="center"/>
</FrameLayout>
Update based on your comments
This does the entire layout dynamically, no button in the XML needed. Replace TextView or ImageView with your button. Change parameters accordingly.
public class BlahActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout rl = new FrameLayout(this);
rl.addView(cv, GlobalVars.screenWidth, GlobalVars.screenHeight);
setContentView(rl);
ImageView fs = new ImageView(this);
fs.setImageResource(R.drawable.icon);
rl.addView(fs);
TextView fs = new TextView(this);
fs.setText("Bar seco");
fs.setTextColor(android.R.color.white);
fs.setTextSize(1,14);
fs.setLayoutParams(new ViewGroup.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
rl.addView(fs);
}
}
I am using a DraggableGridView from here.
What I did before was add a simple programmatically built ImageViews to the grid. That works perfectly fine.
I am now trying to add a Layout instead. I tried RelativeLayout, Framelayout, FrameLayout inside of a RelativeLayout.
Here is my code as of now:
/**
* Rebuild the grid view, e.g. after the adapter has been filled or a backup is restored
*/
private void renewGrid()
{
dgv.removeAllViews();
for(int i = 0; i < adapter.getCount(); i++)
{
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
dgv = (DraggableGridView) inflater.inflate(R.layout.grid_item_layout, dgv);
FrameLayout fl = (FrameLayout) dgv.findViewById(R.id.grid_images);
ImageView icon = (ImageView) fl.findViewById(R.id.qstile);
icon.setImageDrawable(res.getDrawable(res.getIdentifier("qstile_" + adapter.getItem(i), "drawable", packagename)));
}
}
Following the grid_item_layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/grid_images">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="#drawable/icon_delete"/>
<ImageView
android:id="#+id/qstile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
<TextView
android:id="#+id/invisible_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=""
android:visibility="gone" />
</RelativeLayout>
The RelativeLayout gets inflated into the grid nicely. I can observe this via DDMS and the "Dump view hierachy" function. The tree shows all RelativeLayouts inside the grid, but each of it doesn't have any children.
BUT... That is not true. If I step through the code and observe the inflated layouts I can see the children. So they are set up, get added just like told in the XML, but don't get drawn.
The OnItemClick listener on the children of the grid also works...
Any hint about what I'm missing here? I already tried several ways, even creating the complete layout programmatically and then adding it to the grid as children. Still no luck. None of the children get added.
Is that maybe an issue with the used DraggableGridView?
After searching for another few hours I found a fix in this SO thread
Basically I now extend DraggableGridView from FrameLayout rather than ViewGroup. This hasn't had any noticeable side effects to me.