Change linearLayout to dark with all content - android

I would like to do the same effect with linearlayout like when you call showDialog. It is easy to disable all components of linear layout, but how can I change the color?
Is it possible to throw some shadow on layout?
Thank you for answer.

Thanks to Asok advice I found this:
Set Alpha/Opacity of Layout
It is working correct for me.
The way how I setClickable to ALL child:
TraverseChildren(GetChildren(_llRest), false);
where
private void TraverseChildren(ArrayList<View> childrenList, boolean b) {
for (View view : childrenList) {
view.setClickable(b);
view.setEnabled(b);
if (view instanceof ViewGroup)
TraverseChildren(GetChildren((ViewGroup)view), b);
}
}
private ArrayList<View> GetChildren(ViewGroup view) {
ArrayList<View> children = new ArrayList<View>();
for (int i = 0; i < view.getChildCount(); i++)
if (view.getChildAt(i) != null)
children.add(view.getChildAt(i));
return children;
}

I don't think I understood well what you want to do. If you just want to change the color of the layout you can do it in the XML declaration using the android:background attribute or programmatically using the method setBackground or setBackgroundResource on your layout object. If you want to make the activity that you are going to display look somewhat like a dialog (with a translucent background and such) the easiest way is to leave everything on that layout like you would normally do and apply a theme to the activity on the manifest:
<activity android:theme="#android:style/Theme.Dialog">

You can setAlpha to the parent to apply a transparency to all of the Views children.
Here is an example of the approach I took when I created a View to overlay my primary layout:
RelativeLayout mainRelativeLayout = (RelativeLayout)findViewById(R.id.mainlayout);
mainRelativeLayout.setAlpha((float).45);
My mainRelativeLayout, in this case, contains many ImageViews and TextViews which all inherited the transparency. Which gave me the effect of having a shadow.
setAlpaha of the View class is only supported for API 11+ or Platform Version / Android OS Ver 3.0+

Related

Changing a layout depending on a property in android

I have created a custom UI in Android Studio which inherits from LinearLayout. Essentially, it is an edit text with a blue semi-rounded rectangle in it that text can be placed in.
I've added an enum property called borderSide which has the values right and left. By default, the border is on the right. What I'm trying to do is have a condition that when borderSide is left, a different layout is selected so the blue semi-rounded rectangle is on the left. Having searched around, I can't see any simple way to do this.
Currently, I have this (apologies if it's a bit messed up, it's on a different machine)
In drawable, I have two files; supplemental_edittext and supplemental_edittext_left. These are selectors for the different pressed, enabled and focus states and select a drawable. Left means it selects the drawable set for the left side of the edittext. The drawable sets up the border and the rectangle.
The base class (ValidLayout) for the layout inherits LinearLayout, and has a couple of properties for error text. It also inflates a simple layout which contains two text views for a title and the error text. It has an edittext widget in which is added in #override public void addView - it looks like this
#Override
public void addView(View child, int index, ViewGroup.LayoutParams params)
{
if (child instanced EditText)
{
if (editText != null)
throw new RuntimeException("You can only add 1 child");
editText = (EditText) child;
super.addView(child, 1, params);
}
else
{
super.addView(child, index, params);
}
}
The class I've set the borderSide property in (SupplementEditText) extends from the base class and has a method in called setBorderSide(int side). There is a test for edittext (created above) which first checks if it's null and if it isn't sets the background. The code for the change looks like this
public void setBorderSide(int side)
{
if (edittext == null)
return;
borderSide = side == 0 ? false : true;
editText.setBackgroundResource(borderSide ? R.drawable.supplemental_edittext : R.drawable.supplemental_edittext_left);
}
The initial call to setBorderSide is made in the Initialise method.
Together in xml, they work like this
<ValidLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/vlEditText"
app:borderSide="left">
<SupplementEditText
android:layout_width="match_content"
android:layout_height="wrap_content"
android:id="#+id/sEditText"
app:supplementTextPosn="end"
app:supplementText="Hi" />
supplementTextPosn and supplementText are two properties in SupplementText that sets the text and text position at the left or right of the EditText inside of the semi rounded rectangle created in the base class
There seems to be two problems though. Firstly (and this is probably the big on), edittext is null. If I remove the check though, the border remains always on the left irrespective of what I set borderSide to.
In AndroidStudio, is there a way to test what is going on and why it's misbehaving and more over, a way to swap from supplemental_edittext to supplemental_edittext_left

Custom child view bringToFront not working as expected

I have a custom view added as a child of a LinearLayout. I need this custom view to anchor to the bottom irrespective of the parent viewgroup. Here's how I'm doing it.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!drawn) {
drawn = true;
Rect rect = new Rect();
((View) getParent()).getGlobalVisibleRect(rect);
setY(rect.bottom - rect.top - getContext().getResources().getDimension(R.dimen.bottom_bar_height));
setZ(UiUtils.dpToPx(8f));
forceLayout();
bringToFront();
} else {
binding.bottomBarLl.draw(canvas);
}
}
When I add the custom view to a LinearLayout parent, if the children above this child have match_parent height, this one doesn't show.
Below is a screenshot from the layout inspector where it is shown to be laid out but doesn't show.
The inspector also shows that the getZ() of the custom view is 24.
I'm building for API level 21+ but I've also tried ((View) getParent()).invalidate(); and getParent().requestLayout(); in the onDraw() to no good.
From the documentation for View.bringToFront()
bringToFront
Added in API level 1
void bringToFront ()
Change the view's z order in
the tree, so it's on top of other sibling views. This ordering change
may affect layout, if the parent container uses an order-dependent
layout scheme (e.g., LinearLayout). Prior to KITKAT this method should
be followed by calls to requestLayout() and invalidate() on the view's
parent to force the parent to redraw with the new child ordering.
this should be working, but it isn't for me. What am I doing incorrectly?
Like other questions which couldn't get it to work with a LinearLayout, I also used a coordinator layout finally where the linear layout and my custom view are siblings and things are working fine. It would be great if someone could explain the documentation though, since it is misleading otherwise.

How to change the color of the text inside a View?

I have some Views in my Activity that I inflate and populate at runtime.
The View itself is a RelativeLayout to which I add at runtime several TextViews.
When the View is selected I change the color of the background (and that is easy).
Now I need to change the color of all the TextViews inside the View.
Please how do I do that?
Consider that I do not have a reference to the TextViews themselves, since they are created at runtime, nor do I know how many are in there.
Consider that I do not have a reference to the TextViews themselves
Since you "add at runtime several TextViews", you are certainly welcome to "have a reference to the TextViews themselves". Add them to some sort of collection (e.g., ArrayList<TextView>) at the time when you "add at runtime", then iterate over the collection to change their color.
You can do this another way:
Iterate over all children of the RelativeLayout (which you have a reference to):
for (int i = 0; i < mRelativeLayout.getChildCount(); i++) {
if (mRelativeLayout.getChildAt(i) instanceof TextView) {
// Set text color
((TextView)(rl.getChildAt(i))).setTextColor(Color.RED);
}
}
Be careful about mRelativeLayout.get(i) instanceof TextView. This will return true for all Views returned by mRelativeLayout.getChildAt(i) that are subclasses of TextView. For example, if you have a Button inside mRelativeLayout, instanceof will return true since Button extends TextView. To avoid this, use:
if (mRelativeLayout.getChildAt(i) instanceof TextView &&
!(mRelativeLayout.getChildAt(i) instanceof Button))

display view on top of action bar

Is there a way to render a view on top of the action bar? I want to create a small tip box that will point the user to an item in the action bar. I know that a Toast with a set view will be rendered above the action bar. Does anyone know how to do this with a view?
I have attempted using FrameLayout with layout_gravity="top" and inflating a view and then adding it to the running activity's layout.
I appreciate you in advance.
Edit:
Here is an image of what I was thinking:
Edit:
Perhaps some more detail is needed. I am looking for a way, or to find out if it is even possible to add a view to the view hierarchy of the activity so that it is rendered last.
Similar to CSS, I want a higher z-index order for this particular view ( the blue floating box in the image), such that it would be rendered on top of the Action Bar region in the activity. The view is in no way associated with Action Bar, it is simply drawn on top of it.
I was trying to achieve something else but I needed a solution similar to this. I needed to draw an opaque layer covering the whole screen, even the action bar--sort of like a dialog. I did so this way:
ViewGroup vg = (ViewGroup)(getWindow().getDecorView().getRootView());
vg.addView(myNewView, params);
this can be used to draw anything anywhere on the screen.
UPDATE: You really shouldn't be using ActionBar anymore, you wouldn't have this issue in the first place if you were using Toolbar like Android recommends. Toolbar would go inside your activity xml like a regular view and you can can do whatever you want to it. And its fully backwards compatible.
https://developer.android.com/training/appbar/setting-up
After struggling with it myself quite some time, here's the solution (tested it - working good):
The general steps are:
Create a wrapper view
Detach the screen view children, place the wrapper, and attach the children
Inflate the content to the children
Controling the wrapper will help you control exactly the action bar and the content below it all together.
Now, using the wrapper, you can add "brothers" to the actionbar/main area. That brother is exactly what you described in your image.
Let's see some code.
First, create a method to help create a wrapper view. the wrapper will be placed between the entire screen and the content of your app. being a ViewGroup you can later on fully control it's content.
private ViewGroup setContentViewWithWrapper(int resContent) {
ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0);
// Removing decorChild, we'll add it back soon
decorView.removeAllViews();
ViewGroup wrapperView = new FrameLayout(this);
// You should set some ID, if you'll want to reference this wrapper in that manner later
//
// The ID, such as "R.id.ACTIVITY_LAYOUT_WRAPPER" can be set at a resource file, such as:
// <resources xmlns:android="http://schemas.android.com/apk/res/android">
// <item type="id" name="ACTIVITY_LAYOUT_WRAPPER"/>
// </resources>
//
wrapperView.setId(R.id.ACTIVITY_LAYOUT_WRAPPER);
// Now we are rebuilding the DecorView, but this time we
// have our wrapper view to stand between the real content and the decor
decorView.addView(wrapperView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
wrapperView.addView(decorChild, decorChild.getLayoutParams());
LayoutInflater.from(this).inflate(getActivityLayout(),
(ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);
return wrapperView;
}
Now, interfere with the regular Activity creation, and instead of using setContentView, use the method we've created.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DON'T CALL `setContentView`,
// we are replacing that line with this code:
ViewGroup wrapperView = setContentViewWithWrapper(R.layout.activity_layout);
// Now, because the wrapper view contains the entire screen (including the notification bar
// which is above the ActionBar) I think you'll find it useful to know the exact Y where the
// action bar is located.
// You can use something like that:
ViewGroup actionBar = (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(0);
int topOffset = actionBar.getTop();
// Now, if you'll want to add a view:
// 1. Create new view
// 2. Set padding top - use "topOffset"
// 3. Add the view to "wrapperView"
// 4. The view should be set at front. if not - try calling to "bringToFront()"
}
That's about it.
Notes
I've used Android's hierarchy-viewer to understand what's the right hierarchy. (didn't guess those 0 and 1 indexes)
If you are using some kind of a menu drawer in your activity, you might have to configure it a little bit different since drawers are already creating that wrapper for you
I've learned a lot by looking at this great library
EDIT: Refer to #CristopherOyarzĂșnAltamirano Answer for further support on newer Android versions
Good luck!
There is a much simpler way to achieve this. ActionBar holds its layout in the class ActionBarContainer which simply inherits from FrameLayout. So in order to display something over the ActionBar you need to grab a reference to the ActionBarContainer and add your own custom View into it. Here is the code
int abContainerViewID = getResources().getIdentifier("action_bar_container", "id", "android");
FrameLayout actionBarContainer = (FrameLayout)findViewById(abContainerViewID);
LayoutInflater myinflater = getLayoutInflater();
View customView = myinflater.inflate(R.layout.yourCustomeViewLayout, null);
actionBarContainer.addView(customView);
I found this workaround based on #Sean answer:
//This is for Jelly, ICS, Honeycomb
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){
LayoutInflater.from(this).inflate(resContent, (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);}
//This is for KitKat and Jelly 4.3
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){
LayoutInflater.from(this).inflate(resContent, (ViewGroup) (((ViewGroup) wrapperView.getChildAt(0)).getChildAt(0)), true);}
//This is for Ginger
else{
LayoutInflater.from(this).inflate(resContent, (ViewGroup) ((LinearLayout)((FrameLayout) wrapperView.getChildAt(0)).getChildAt(0)).getChildAt(1), true);}
I found a much simpler way to do this.
I just applied android:translationZ="10dp" to the view which I need to be covering the action bar.
I chose 10dp but it can actually be anything you want as long as it is superior to the actionbar's elevation
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:translationZ="10dp"
android:src="#drawable/potatoe" />
Also, don't worry about Android studio's following warning :
"translationZ can't be used with API<21".
It will be ignored, but you don't really care because the toolbar shouldn't cover your view with APIs inferior to 21.
Try using ActionBar.setCustomView(). That's the only way to change the appearance of that area of the screen. You can't stick a View into the area "above" the ActionBar, because that area is basically controlled by the system. On the other hand, you can provide your own layout for it.
If you explain in more detail what you're trying to do, respondents might have some better design ideas.
https://github.com/michaelye/EasyDialogDemo
see the demo above,it may help you
dialog.setLocation(new location[])//point in screen
you could set the location[] yourself.
Use the android:actionLayout in your menu.xml file.
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_id"
android:title="#string/menu_string_to_show"
android:icon="#drawable/ic_menu_icon_name"
android:showAsAction="always"
android:actionLayout="#layout/action_button_foo" /></menu>
Then create your action_button_foo.xml layout:
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/menu_string_to_show"
android:drawableLeft="#drawable/ic_menu_icon_name"
android:background="#drawable/bg_btn_action_bar"
android:clickable="true" />
To handle click do the following:
#Overridepublic boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
final MenuItem item = menu.findItem(R.id.menu_id);
item.getActionView().setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(item);
}
});
return super.onCreateOptionsMenu(menu);}
That's if :)
(Reference: http://www.vogella.com/articles/AndroidActionBar/article.html)Custom Views in the ActionBar
You can also add a custom View to the ActionBar. For this you use the setCustomView method for the ActionView class. You also have to enable the display of custom views via the setDisplayOptions() method by passing in the ActionBar.DISPLAY_SHOW_CUSTOM flag.
For example you can define a layout file which contains a EditText element.
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/searchfield"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textFilter" >
This layout can be assigned to the ActionBar via the following code. The example code allow attaches a listener to the custom view.
package com.vogella.android.actionbar.customviews;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
search.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
Toast.makeText(MainActivity.this, "Search triggered",
Toast.LENGTH_LONG).show();
return false;
}
});
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
}
}
The explanations here are all too long:
Wrap your main layout file into a top level ViewGroup (e.g. wrap a CoordinatorLayout into a FrameLayout), then inject or declare the view in the new top level layout out. The view will appear above the action bar.

Is it possible to disable all widgets by disabling their wrapping layout?

I tried to disable the children widgets by disabling the wrapping relativeLayout, but that doesn't work, is there any other way to do that? I think this is necessary because sometimes we don't want to setEnable(xx) on every children widgets. So is it possible for me to do that? or is there some similar way ? thx a lot~
Maybe you can try something like this:
RelativeLayout myLayout = (RelativeLayout findViewById(R.id.linearLayout1);
for ( int i = 0; i < myLayout.getCount(); i++ ){
View view = myLayout.getChildAt(i);
view.setEnabled(false); // Or whatever you want to do with the view.
}
I believe you can extend the layout class and implement a new method that does the job. Also, you can check this question: How to disable all content inside linear layout in android?

Categories

Resources