I have a LinearLayout in which a TextView's visibility and background (GradientDrawable) changes according to a function myFunction():
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:animateLayoutChanges="true"
android:gravity="center"
android:orientation="vertical" >
(...Some views...)
<TextView
android:id="#+id/currentPercentage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:gravity="center"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:singleLine="true"
android:text="XX.X%"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/White" />
</LinearLayout>
The currentPercentage TextView has GONE visibility by default and, according to some events in the fragment that contains it, may have it changed to Visible (or back to GONE) and its background to a different GradientDrawable like so:
myFunction(...){
TextView currentPercentage= (TextView) getView().findViewById(R.id.currentPercentage);
if(condition ... ) {
Color color = // Color based on the condition...
GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TL_BR,
new int[] {color,color});
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int dp = Math.round(10f / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
gd.setCornerRadius(dp);
currentChartPercentage.setBackground(gd);
} else if( otherCondition...)
{
// ... similar stuff ...
} else {
// Hide the currentPercentage TextView
currentPercentage.setVisibility(View.GONE);
}
}
This works fine as the TextView's background and visibility change smoothly whenever myFunction() is called and the other elements in the LinearLayout move (with animation) to make room for the TextView.
My issue is that whenever the visibility goes from GONE to VISIBLE, the View fades in nicely (as expected because of android:animateLayoutChanges="true") but right in the end shows up with an annoying black background where the GradientDrawable round corners are (see image).
Right after that, if I touch something else or drag the fragment (it's inside a ViewPager), the black background disappears. If myFunction() is called again, with the View already VISIBLE, then the background color changes as desired with no black background.
Also, if I disable the animation, I don't get the black background too. Thus, the problem seems to be related to the visibility going from GONE to VISIBLE with an animation.
This behavior is obtained on an emulator with Android 4.3 and I haven't tested it on my real device yet.
Does anybody have a clue on why this may be happening?
EDIT:
Just tested this on a real device with ICS without any issue.
EDIT 2:
I once had a problem with an undesirable background showing up in a ListView similar to Background ListView becomes black when scrolling but in this case, setting a cacheColorHint does nothing.
Related
i'm here to ask if anyone knows a workaround to the issue i'm failing to fix.
Basically i'm coding a simple Chat App in Android using Firebase as an exercise. I'm using a ListView in my main layout and a simple Layout to use for each "message bubble". Here comes the problem: when i visualize the messages that i retrieve from Firebase i change the color of the bubble based on the current user in runtime, when first loaded each bubble has the right color, but by scrolling up and down my messages more and more bubbles take on the "ActiveUser" color even if they belong to different users, any ideas? I'll leave the code i'm using down below
Main Layout ListView
<ListView
android:id="#+id/list_of_messages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/inputArea"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:divider="#android:color/transparent"
android:dividerHeight="16dp"
android:paddingStart="15dp"
android:paddingBottom="5dp"
android:paddingEnd="15dp"
android:paddingTop="10dp"/>
Message Bubble Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:id="#+id/message_bubble"
android:background="#drawable/normal_message_background">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/message_user"
android:textStyle="normal|bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/message_user"
android:layout_marginStart="10dp"
android:id="#+id/message_time" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/message_user"
android:layout_alignParentStart="true"
android:layout_marginTop="5dp"
android:id="#+id/message_text"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textSize="18sp" />
FirebaseListAdapter and runtime style change code chunk
private void displayChatMessages() {
ListView listOfMessages = findViewById(R.id.list_of_messages);
FirebaseListOptions<ChatMessage> options = new FirebaseListOptions.Builder<ChatMessage>().setLayout(R.layout.message)
.setQuery(dbMessagesReference, ChatMessage.class).build();
mAdapter = new FirebaseListAdapter<ChatMessage>(options) {
#Override
protected void populateView(View v, ChatMessage model, int position) {
// Get references to the views of message.xml
RelativeLayout messageBubble = v.findViewById(R.id.message_bubble);
TextView messageText = v.findViewById(R.id.message_text);
TextView messageUser = v.findViewById(R.id.message_user);
TextView messageTime = v.findViewById(R.id.message_time);
// Set their text
messageText.setText(model.getMessageText());
messageUser.setText(model.getMessageUser());
messageTime.setText(model.getMessageTime());
if (messageUser.getText().equals(FirebaseAuth.getInstance().getCurrentUser().getDisplayName()))
messageBubble.setBackgroundResource(R.drawable.active_user_message_background);
}
};
listOfMessages.setAdapter(mAdapter);
}
EDIT:
I've fixed the problem by declaring the else statement to set the normal drawable variant back if the usernames did not match, however once changed the background Resource in runtime the bubble looks smaller and doesn't wrap around all the text, does anyone know the reason of this?
2ND EDIT:
I've found the solution to my second problem in this other post: Where'd padding go, when setting background Drawable?
Apparently the issue should have been fixed back in API 19/21, however if you still experience that problem apply the workaround explained in the thread linked above
ListView will reuse views to help with performance. This means when we scroll the adapter will just place your content in a view that was slated to go off screen rather than inflating a new view. This is causing all views that you set the current user background on to always keep that background since you don't have a condition to set it back if the view is filled with non-current user data.
To fix this add the following condition:
if (messageUser.getText().equals(FirebaseAuth.getInstance().getCurrentUser().getDisplayName())){
messageBubble.setBackgroundResource(R.drawable.active_user_message_background);
}
else{
messageBubble.setBackgroundResource(R.drawable.normal_message_background);
}
<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've tried to put the intern icons of Android (anrdoid.R.drawable.bla) into an ImageButton
and I wanted to change the color of Icon (not the Background!), but it doesn't work like I want to.
Here is what I've tried:
my ImageButton from the Layout:
<ImageButton
android:id="#+id/imageButton1"
android:layout_marginTop="100dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background"
android:src="#android:drawable/ic_lock_silent_mode" />
what I've tried in my Activity:
Drawable myIcon = getResources().getDrawable( android.R.drawable.ic_lock_silent_mode);
ColorFilter filter = new LightingColorFilter( R.color.blue, R.color.blue);
myIcon.setColorFilter(filter);
No matter what Values I've tried for the LightingColorFilter it always gives the same result. The icon inside the Imagebutton gets dark. But thats not what I wnated. I just wanted to apply a color from my colors.xml, it somehow doesnt work out.
Is this even the right direction I'm going? Or is there another opertunity (And I don't mean coloring myself in Photoshop and putting them into the drawables folder)
this worked for me, for example it will paint in dark gray:
ImageButton imgBtn = (ImageButton) findViewById(R.id.imageButton11); // image button
imgBtn.setColorFilter(getResources().getColor(android.R.color.darker_gray), Mode.SRC_ATOP);
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: