Change background of a custom view when touched - android

I want to change the background color of a customView when it's pressed and slightly "remove" this background color when the view losses the "pressed-state". However, I googled this question and found a solution using a StateListDrawable. I've tried this within my customView (which is added to a ListView programmatically), but just the "normal color" was set to my view. When I touched the view nothing happens. What's going wrong?
the selector xml-file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#color/bckgr" />
<item
android:drawable="#color/transparent" />
</selector>
within the constructor of my custom view:
this.setBackgroundResource(R.drawable.list_item_bckgr);

you have to apply your background to the View the Adapter fills up (the view your getView implementation is returning) not to the ListView self

Try setting android:descendantFocusability to true on the ListView.

Hey Are you making the view focussable and clickable, use in the constructor:
setClickable(true);
setFocusable(true);
May be your view isn't getting focus.

You need to set the OnTouchListener to handle touch events. When the view is touched, change the background, and when the view is 'untouched', change the background back to the original.
To set the listener, call the View.setOnTouchListener() function of your custom view with the OnTouchListener you create to handle these events.
Here is the reference to OnTouchListener:
http://developer.android.com/reference/android/view/View.OnTouchListener.html

I imagine that you have an override method to the OnTouch() method, what I would do is create an instance variable (class var) that would hold the image that you want to have as a background, and set it in your OnTouch() method. Then, Override your OnDraw() method which would give you a reference to the canvas, and use the canvas.DrawBitmap() to draw your background.
This answer shows you more details on how to draw the bitmap
Setting background image in a custom view

Related

Android custom ArrayAdapter | Change icon on ImageView click

I have a list with elements that use a custom layout which consists of a text view and an image view. For this, I follow ViewHolder pattern like explained here. The image views display one of two icons and I want to change the icon of the clicked image view.
So my first approach was to define the on click listener of the ImageViews in the overridden getView function of my adapter class. The problem is that when the icon of the first ImageView changes and I scroll down to the last its icon changed as well. This question here was not helpful.
Here I found that it's not the best way to handle the click in the getView function but it's better to do it in the listView.setOnItemClickListener. I tried it but I am not able to find out whether an ImageView was clicked or not as the parent object holds the list item and the view parameter the LinearLayout in which the ImageView is contained (even when I click directly in the ImageView). Setting android:focusable="false" of the outer LinearLayout as it is suggested here did not help.
I'm sure someone must have had this issue / use case but I'm not able to find a solution. So, what's the best way to handle the click of the ImageView in my custon list item view?
Try adding the following attributes to the clickable ImageView instead of its ViewGroup, your LinearLayout:
android:focusable="false"
android:focusableInTouchMode="false"
... and as far as updating UI in a AdapterView/ListView/RecyclerView goes, you should make good use of an int flag that tracks the position of the list item that was clicked, and then set it as a conditional statement in getView() before invoking notifyDataSetChanged(), since "every other" row will be updated, especially in lists of say, 100 rows.
I actually answered this in a similar question here and here.
If you have two icons, you can simply put a custom checkbox instead of an imageview :
<CheckBox
android:id="#+id/customchechecbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/checkbox_selector"
android:button="#android:color/transparent" />
checkbox_selector :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/checkbox"
android:state_checked="false"/>
<item android:drawable="#drawable/checkboxselected"
android:state_checked="true"/>
<item android:drawable="#drawable/checkbox"/>
</selector>

Android: Generic clickable view with visual feedback

I need to implement a generic method which makes View-objects clickable. This is my current implementation:
public static <V extends View> V clickable(V view, OnClickListener listener) {
view.setFocusable(true);
view.setClickable(true);
view.setFocusableInTouchMode(true);
view.setOnClickListener(listener);
return view;
}
It works. The problem now is to add visual feedback for the user. I would like to somehow visualize the focus and the click.
An example would be the section titles in Google Play Store. The section titles look like normal text with a fake button, but when touching them, the whole background (text and fake-button) changes.
I know about the solution with xml-files, where I have to specify <selector> and <item android:state_pressed="true"> and so on.
But how to implement the focus/click visualization in my generic method?
you can assign a background drawable to the view which has selectors defined in it using:
setBackground
setBackgroundResource
you may have to qualify the call based on the platform if you are supporting older phones.

Viewgroup draw not called again after background manipulation

I have a custom ViewGroup that overrides draw() to draw some stuff over its children. It calls setWillNotDraw(false) on the constructor appropriately, and under normal conditions, works as intended.
My problems start when, in the layout XML, on such view I assign a background drawable ("splash screen") and later on in the application I remove this background (setBackgroundDrawable(null)). This happens only once, while application is initializing.
<com.regaliz.gui.layouts.FunqRootLayout xmlns:android="..."
.
android:background="#drawable/a_filmnew_cover_play_splash">
From that point, onDraw / draw is never called again whenever I invalidate the ViewGroup.
I've checked the View.java's setBackgroundDrawable source code and saw a lot of logic to manipulate the View Flags to add or remove WillNotDraw-related internal flags (but all the methods are private). I suspect this is what's happening: The call to setBackgroundDrawable(null) sets the willNotDraw flag), however I am not able to enable it again.
Subsequent calls to
setWillNotDraw(false)
are ignored.
To make things funnier, if I don't assign any background in the XML, the setBackgroundDrawable(null) call doesn't seem to touch the flags, so I don't have this problem.
What can be happening?
This is the splash drawable:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:src="#drawable/a_filmnew_cover_play" />
try overriding dispatchDraw(Canvas) method

onItemClick in ListView randomly changes the background color

I am using multiple choice ListView items. The user can select multiple items. So I wanted to highlight the items selected by the user by changing either the text color or background color of the list row. I have gone through stack overflows links but didn't get the proper solution. When I am trying to do it, it is randomly changing any unselected item background color. Help!!!
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
videocursor.moveToPosition(position);
v.setBackgroundColor(Color.parseColor("#80B7DBE8"));
SaveSelections();
}
That randomly changing background color is due to the reason that ListView recycles views in its list to avoid unnecessary memory consumptions. You need to provide your own custom adapter in which you need to override getView method and perform some checks to highlight only those list items who have some kind of flag set to true for background color
Far better than the above suggestions is to use a selector, also known as a state-list drawable. That way, the OS takes care of all of the business of color highlighting, etc.
more explicitly, take the following xml and save it under res/drawable as something like li_background.xml (I'm using images, but feel free to swap out colors as is appropriate to your situation)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_focused="true"
android:drawable="#drawable/list_item_pressed" />
<item android:state_pressed="true"
android:drawable="#drawable/list_item_pressed" />
<item android:state_selected="true"
android:state_activated="true"
android:drawable="#drawable/list_item_selected" />
<item android:state_activated="true"
android:drawable="#drawable/list_item_selected" />
<item android:state_selected="true"
android:drawable="#android:color/black" />
<item android:drawable="#android:color/transparent" />
</selector>
and set the background of All ListItems in the ListView to R.drawable.li_background. if your listView is properly configured for multiple selections (android:choiceMode="multipleChoice" or listView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); if you prefer) then android will take care of the rest. This stuff isn't well documented, I had a hard time finding the solution and I see similar questions all the time, but the relevant dos are here and here
Wagas is correct. In your adapter's getView, you are passed a View (called convertView by Eclipse's autocomplete). This is because ListViews recycle the views for each row. If you set a property for a given View, it will retain that property when it is recycled.
For this reason, you should never set the properties of anything in a given row's View outside the getView method of the Adapter backing the ListView.
There are a number of ways you could handle this, but the basic idea is that you want to set some piece of data that uses the position passed in to onItemClick to set a flag. Then check the flag in the Adapter's getView to decide how to set the background for the row's View.
For example, if only one item can be selected, you might just set a member variable, say mPosition on the Adapter itself to the position passed in to onItemClick, and then check in getView if position == mSelectedPosition to decide how to set the View. If multiple items can be selected, perhaps you set a member variable on each object contained in the Adapter.
You probably should override getView() in the adapter, and change the row background color in there.
An example:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView != null) {
if (mSelectedPositions.contains(position)) {
convertView.setBackgroundColor(Color.parseColor("#3fa9f5"));
} else {
convertView.setBackgroundColor(Color.parseColor("#ffffff"));
}
}
return super.getView(position, convertView, parent);
}
in onItemClick() just use adapter.notifyDataChange(); also set a flag to true;
in the getView() of your CustomAdapter use boolean flag to know whether the row was selected or not.
Then just check that flag and proceed as you want
i.e.,
if(flag){
v.setBackgroundColor(Color.parseColor("#80B7DBE8"));
}else{
v.setBackgroundColor(Color.parseColor("#FF0000"));
}

Add draggable shape on a picture in Android

Can anyone explain how can I add shape (for example a rectangle or an arrow) on to a image (in ImageView)? Once added, the shape will need to be draggable to anywhere in the image. And finally need to save the image edited (with the shape on top of that).
What informations do you really need?
This can be some steps to do:
Maybe create a new object to handle this:
Create a new class and extend from ImageView or use LayerDrawable for that.
Write setters/getters for the main-background-image/bitmap.
Add your own Vector shape (create a new class with definable color,thickness... or hard-code it)
Do all of your drawings in onDraw-Methods
Implement onTouch interfaces to handle your selection and dragging.
Create new method (render to jpeg/png/..) to save your resulting image
Create a Custom view from View that completely overlaps your ImageView. This view will have a transparent background and contain the draggging view. Initially set visibility to invisible.
In Custom view class override the onTouch event where you update the dragging views margins.
On save, get drawing cache of the parent layout(that contains both the ImageView and Custom view) and use as needed.
Sample xml code:
Relative layout parent whose drawing cache has to be grabbed using rel.getDrawingCache()
<RelativeLayout .......>
<ImageView ......./>
<CustomView ......./>
</RelativeLayout>

Categories

Resources