I'm trying to restore the background Color of a View.
I have several selectable Views. When the user clicks one of those Views, the following code is executed and the View becomes Yellow:
View newSelection, previousSelection;
...
if(previousSelection != null) {
previousSelection.setBackgroundColor(Color.BLACK); // problem here
}
newSelection.setBackgroundColor(Color.YELLOW);
However, I want to reset the color of the previously selected View. However, I do not know which color it was (I'm setting it to Color.BLACK in the above code). I was not able to find a getBackgroundColor or similar method in the View class. If I had it, I could save the previous color and just put it back when the new View is selected.
use View.getBackground(), it returns the current 'Drawable' background of the view which can then be used in View.setBackgroundDrawable()
View theView;
Drawable originalBackground;
...
originalBackground = theView.getBackground();
theView.setBackgroundColor(Color.YELLOW);
...
theView.setBackgroundDrawable(originalBackground);
I'm not sure exactly what you are trying to accomplish but perhaps a ColorStateList would come in handy here.
You can try setting the previous color as a tag of the view.
For example
View newSelection, previousSelection;
newSelection.setTag(Color.Green);
previousSelection.setTag(Color.Black);
if(previousSelection != null) {
previousSelection.setBackgroundColor((int)previousSelection.getTag());
}
newSelection.setBackgroundColor(Color.YELLOW);
I haven't tried the code if there is an error but the flow on how to implement is there.
Related
I have a RecyclerView in which a selected number of items show a different background color.
It gave me with many views with different color.
I used the position of adapter to change color and later I found that position changes when scrolling.
So I gave a unique code to every object of the ArrayList. And I gave the program to change background color if the unique code matches the given code.
Like,
uniqueCode = 5;
public void onBindViewHolder(//..){
Object object = objectArrayList.get(i);
if(object.uniqueCode() == uniqueCode ){
holder.layout.setBackgroundColor(//....);
}
}
But still I get some views changes the background color on scrolling which does not match that unique Id.
What is the solution to this problem ?
If i understand correctly there are multiple cells with the "unique" color but it shouldn't. This happens because you never reset the background of the layout to the default color.
if(object.uniqueCode() == uniqueCode){
holder.layout.setBackgroundColor(/*unique color*/);
}
else{
holder.layout.setBackgroundColor(/*default color*/);
}
I am trying to set a RippleDrawable as background to a list view row.
When using view.setBackgroundResource(R.drawable.ripple) everything works fine.
When trying
view.setBackground(view.getContext().getDrawable(R.drawable.ripple))
it works but the ripple doesn't show when quickly touching the item (I also have an activated/checked state for the item), it appears only when I keep the view pressed.
The setBackgroundResource method in View class looks like this :
if (resid != 0 && resid == mBackgroundResource) {
return;
}
Drawable d = null;
if (resid != 0) {
d = mContext.getDrawable(resid);
}
setBackground(d);
mBackgroundResource = resid;
so basically the exact thing I am trying to do manually.
NOTE: I want to use setBackground method because I want to create the RippleDrawable programatically.
Does anybody have an idea why this is happening ?
Instead of setting the ripple on the row View, set it on the ListView using the listSelector attribute:
<ListView
...
android:listSelector="#drawable/ripple" />
Programmatically you can set it with mListView.setSelector(...).
call View.invalidate(); along with View.requestLayout();
the CompoundButton function setChecked(boolean) when used invalidates the View hence the View is asked to re-check itself and then re-drawn or layed out
I have a row in a listview activity where an image should be changed when the row is selected. The new image is identical but larger (double size) than the original image. It is supposed to be reduced when it is deselected (Selection is implemented using my internal selection, not the android keyboard selection kind) again.
Problem is when (selected) I change the picture (at the time of bind) of my ImageView () using setImageResource() it does not update to the new larger version in my List row on the first click. Second execution of bind works fine. The same applies for the old item being deselected. The change to a smaller icon does not get in effect until a second click. The problem repeats itself each time I select another row than the currently selected and starts working correctly again on the second click.
I have stepped through code and seen that I pass the right id to the ImageView and this is prooved by the fact that another View showing a yellow border on the same row is changed to visible/hidden when selected/deselected.
To me it feels like the setImageResource() does not refresh the view immediately, but using invalidate() on the view or the row has no effect at all.
Is this a bug (how to work around) or do I do something wrong?
Code: (from my holder class using the holder pattern - executed by the adapter bind method)
#Override
public void refreshFromCursor(final Context context, final Cursor cursor) {
...
boolean selected = adapter.getSelectedPosition()==cursor.getPosition();
if (selected){
selectedIndicator.setVisibility(View.VISIBLE); // Show a "selected" yellow border indicator to the left
} else {
selectedIndicator.setVisibility(View.GONE); // Hide a "selected" yellow border indicator to the left
}
...
if (selected) completionResId = R.drawable.folder_selected;
else completionResId = R.drawable.folder;
...
statusIcon.setImageResource(completionResId); // !!!!! This is where I set the image that does not refresh/resize
...
}
Also tested exchanging the
statusIcon.setImageResource(completionResId);
with
statusIcon.setImageDrawable(context.getResources().getDrawable(completionResId));
but nothing changes in the problematic behaviour
In my opinion it is about the way you have implemented,
if you provide us the full code of refreshFromCursor(...) function we can have better understanding of what you did.
I found a hack. just make your drawable bigger
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="500dp"
android:height="500dp"
android:viewportWidth="139"
android:viewportHeight="139">
<path
android:fillColor="#000000"
android:pathData="M117.037,61.441L36.333,14.846c..." />
</vector>
here I set the drawable to be drawn on a 500dp canvas (instead of a 139dp one that was there originally) and it did the trick. no more weird tiny icons that later increase in size.
I am working on an android application. I have created a listview by using
setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,arrayname));
getListView().setTextFilterEnabled(true);
Now i want to change the selected item's color. I could change the background of the selected item by placing
listviewobject.getChildAt(position).setBackgroundColor(Color.BLACK);
in onListItemClick()
this code is changing the background color but if I select any other list item then also the previously clicked list item's color is red.So I change the previously clicked listitem's color by
l.getChildAt(prevpos).setBackgroundColor(Color.BLACK);
now the problem is if i change the background of previously clicked listitems color to black.Then i can't see the text on that particular listitem.I i click again then only i can see the text on that item.So its look weired.please help me friends
After going through lots of posts and blogs i found this solution it works for me...
declare row variable global
public View row;
your_list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v,
int position, long id) {
if (row != null) {
row.setBackgroundResource(R.color.orange);
}
row = v;
v.setBackgroundResource(R.color.transparent_green);
)};
Well using this in the properties of your list view mught help:
android:listSelector="#drawable/list_selector"
It will automatically set the selected drawable as background of the selected item. Hope this works for you and drawable may be your own choice's color.
Explanation: Add an image strip to your drawables folder/s and set that image in listSelector attribute of the your list view. Now you will navigate through your list view, the list view's background will be of the color of the image strip you set instead of android's native color. Hope you get it now...:-)
I this This happening because you have put text color as black and your setting the background color also black that's why you can't see the difference. for setting the background color you can use the following line.
view.setBackgroundColor(Color.YELLOW);
use different color then text color.
By default the background is black. If you have customized your listview then when you scroll it would turn black. So when you define your list view set background cache color to the color you need as below:
yourlistView.setCacheColorHint(Color.WHITE);
What you can do is instead of using .setBackgroundColor() with a Color value, create a Color State List and assign it with .setBackgroundResource(). That way, you can define the various states that your list item can become, depending on the item's current state.
I am using a custom title view in my application for each activity. In one of the activities, based on button clicks I need to change the custom title view. Now this works fine every time when I make a call to setFeatureInt.
But if I try to update any items in the custom title (say change the text of a button or a text view on the title), the update does not take place.
Debugging through the code shows that the text view and button instances are not null and I can also see the custom title bar. But the text on the text view or the button is not updated. Has anyone else faced this problem?
How do I resolve it?
Thanks.
EDIT
Here's what I tried. Does not get updated even on calling postInvalidate.
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.text_title);
TextView databar = (TextView) findViewById(R.id.title_text);
databar.setText("Some Text");
databar.postInvalidate();
Button leftButton = (Button) findViewById(R.id.left_btn);
leftButton.setOnClickListener(mLeftListener);
leftButton.setText("Left Btn");
leftButton.postInvalidate();
Button rightBtn = (Button) findViewById(R.id.right_btn);
rightBtn.setOnClickListener(mRightListener);
rightBtn.postInvalidate();
The problem is that the only Window implementation (PhoneWindow) uses a LayoutInflater in its setFeatureInt method and instantiates the new layout with inflate and attachToRoot=true. Consequently, when you call setFeatureInt, the new layouts are not replaced but attached to the internal title container and thus drawn on top of each other.
You can workaround this by using the following helper method instead of setFeatureInt. The helper simply removes all views from the internal title container before the new custom title feature is set:
private void setCustomTitleFeatureInt(int value) {
try {
// retrieve value for com.android.internal.R.id.title_container(=0x1020149)
int titleContainerId = (Integer) Class.forName(
"com.android.internal.R$id").getField("title_container").get(null);
// remove all views from titleContainer
((ViewGroup) getWindow().findViewById(titleContainerId)).removeAllViews();
// add new custom title view
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, value);
} catch(Exception ex) {
// whatever you want to do here..
}
}
I'm not sure whether the current setFeatureInt behaviour is intended, but it is certainly not documented one way or the other which is why I'll take this to the android devs ;)
EDIT
As pointed out in the comments, the aforementioned workaround is not ideal. Instead of relying on the com.android.internal.R.id.title_container constant you could simply hide the old custom title whenever you set a new one.
Let's assume you have two custom title layouts:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/custom_title_1" ...
and
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/custom_title_2" ...
and you want to replace custom_title_1 with custom_title_2, you could hide former and use setFeatureInt to add the latter:
findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);
The correct way to do this is as follows:
requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );
Please note that the order of these statements is very important.
If you call super.onCreate() before any of the other statements you will get a blank title bar, which the hack of finding the title bar id and removing all the Views from it will fix but is not recommended.
Are you calling invalidate or postInvalidate to redraw the view after updating the text? If it's a custom View, can you put a breakpoint in the draw code to make sure it's getting called?
If you're on the UI thread, you can call 'invalidate' if you're not, you must call 'postInvalidate' or the view won't redraw itself.
Just my 2c worth:
When working in a MapActivity, requesting a custom title resulted in no title at all being shown.
Luckily, all I wanted to do was to set the title text differently, and I soon realized that just calling setTitle() inside of onCreate() worked for me (I called it after I called setContentView())
Sorry, but I don't have time right now to debug this any more and figure out why what I was doing didn't work, and why changing it made it work. As I said, just thought this might help someone out down the road.