I am developing an application that have a ListView. In this ListView, when I touch in one item the background color of this item changes, to show that the item is selected.
Howerver, the layout have an EditText too:
<ListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/pratosListView"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:layout_weight="0.8"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:id="#+id/quantidadeEditText"
android:layout_marginRight="#dimen/activity_horizontal_margin"
style="#style/EditText"/>
and when I touch the EditText the item selected in ListView is unselected, in other words, the background color back to the original color. I don't want this happens.
This is my selector (list_item_selector.xml):
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#drawable/item_list_selected"/>
<item android:state_pressed="true" android:drawable="#drawable/item_list_pressed"/>
<item android:state_focused="true" android:drawable="#drawable/item_list_focused"/>
<item android:drawable="#drawable/item_list_normal"/>
</selector>
Here I set the background of the item (item_lista_pedidos.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/activity_all_magim"
android:orientation="horizontal"
android:weightSum="5"
android:baselineAligned="false"
android:background="#drawable/list_item_selector">
.....
</LinearLayout>
And here is the implementation of the click listener:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// salva a posicao do item selecionado
lastPositionSelected = position;
// salva o objeto relativo ao item selecionado
servicoSelected = servicos.get(position);
view.setSelected(true);
}
Someone have some idea to avoid the item to be unselected when I touch in EditText?
As mentioned here, If you want to detect outside touch only outside of EditText, you can detect touch event in the containing view, and then, given you have your EditText view:
Rect editTextRect = new Rect();
myEditText.getHitRect(editTextRect);
if (!editTextRect.contains((int)event.getX(), (int)event.getY())) {
//touch was outside edittext
}
Or you add a touch listener both to the EditText and the container, and return false in the one of the EditText, this way it will be intercepted and not forwarded to the parent. So, all the touches you detect in the listener of the parent, will not belong to the EditText.
Related
Hello i want to change background of my listView item.but it only highlight on touch.but i want to change the background until i change the focus on other item.
What i did so far is below.
Back.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_enabled="false" android:state_focused="true"
android:drawable="#android:color/black" />
<item android:state_pressed="true"
android:drawable="#android:color/holo_red_dark" />
<item android:state_focused="true"
android:drawable="#android:color/holo_red_dark" />
ListView
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:fastScrollEnabled="true"
android:drawSelectorOnTop="true"
android:clickable="true"
android:listSelector="#drawable/listviewcolor"
android:scrollingCache="false">
</ListView>
In Main i have tried everything but does not works it only highlight on touch.
but i want to keep highlight until i change it .
ListView.requestFocus();
ListView.setActivated(true);
ListView.setPressed(true);
ListView.setItemChecked(4, true);
ListView.requestFocusFromTouch();
ListView.setSelection(2);
This can be achieved only by using customAdapter in the following way.
Initially a Listview will lose its focus, when user touches some other item in the layout design. One way of keeping it stay selected, even when it's out of focus is by:
Keeping track of selected position from ListView.
Use the selected position in the ListView adapter and set its view background color according to the selection.
By doing this your background color will stay selected.
Example:
Inside your custom Adapter:
Private int studentListItemSelected;
public void ItemSelected(int itemPosition)
{
//This method will keep track which position of the List is Selected and the background color of it is inside this.
this.studentListItemSelected=studentListItemSelected;
notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent)
{
//layout inflation code
if(this.studentListItemSelected==position)
{
convertView.setBackgroundColor(Color.Red);
}
else
{
convertView.setBackgroudnColor(Color.White);
}
return convertView;
}
In your Layout Java file:
yourListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
adapter.ItemSelected(position);
});
I have a ListView, where each item has a custom LinearLayout with a bg image, a textView and 2 imageViews.
Now I need that while the user is touching the item, all of those switch to the "pressed" state:
the bg image of the LiearLayout must be replaced with another one
the TextView should change textColor
both ImageViews in the item should switch to alternative images
Normally such stuff would be done using an xml resource with selector inside, e.g. the LinearLayout would use a drawable with selector inside for background, the TextView a drawable with selector and colors for textColor, and ImageViews use selector with images inside for src.
The problem is that the pressed state is only detected by the LinearLayout and not by the child views (?), so only the background image changes.
I've tried implementing this using OnTouchListener, but then comes the problem that I can't securely get access to Views inside the list item.
I tried caching the view which I return in getView() of the list item to then later change the images and text color. This works usually, but e.g. if one of the list items opens another activity, then the view somehow gets lost and the highlighted state stays indefinitely. I've tried debugging and it works correctly if I step thru with the debugger.
Also, reusing the cachedView seems to bring no good and messes things up completely, so I'm just inflating a new view for the list item each time (this must be inefficient).
Just in case, here is the code of the custom list item item i'm using for the custom list adapter:
public class MyListItem extends AbstractListItem
{
private int iconResource, iconHighlightedResource;
private int textResource;
private View.OnClickListener onClickListener;
private LinearLayout currentView;
private ImageView imgIcon;
private TextView txtText;
private ImageView imgArrow;
private boolean bIsHighlighted;
public MyListItem(int iconResource, int iconHighlightedResource, int textResource, View.OnClickListener onClickListener)
{
this.iconResource = iconResource;
this.iconHighlightedResource = iconHighlightedResource;
this.textResource = textResource;
this.onClickListener = onClickListener;
}
public View getView(View cachedView)
{
this.currentView = buildView();
populateView();
update();
return this.currentView;
}
private LinearLayout buildView()
{
LayoutInflater inflater = (LayoutInflater)App.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return (LinearLayout)inflater.inflate(R.layout.my_menu_item, null);
}
private void populateView()
{
this.imgIcon = (ImageView)this.currentView.findViewById(R.id.img_menu_item_icon);
this.txtText = (TextView)this.currentView.findViewById(R.id.txt_menu_item_text);
this.txtText.setText(this.textResource);
this.txtText.setTypeface(App.fontCommon);
this.imgArrow = (ImageView)this.currentView.findViewById(R.id.img_menu_item_arrow);
this.currentView.setOnClickListener(this.onClickListener);
this.currentView.setOnTouchListener(this.highlighter);
}
private View.OnTouchListener highlighter = new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
int nAction = event.getAction();
int nActionCode = nAction & MotionEvent.ACTION_MASK;
switch (nActionCode)
{
case MotionEvent.ACTION_DOWN:
bIsHighlighted = true;
update();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
bIsHighlighted = false;
update();
break;
}
return false;
}
};
private void update()
{
if (this.bIsHighlighted)
{
updateForHighlightedState();
}
else
{
updateForNormalState();
}
}
private void updateForHighlightedState()
{
Resources r = App.get().getResources();
this.currentView.setBackgroundResource(R.drawable.button_beveled_m_call_to_action_taking_input);
this.imgIcon.setImageResource(this.iconHighlightedResource);
this.txtText.setTextColor(r.getColor(R.color.white));
this.imgArrow.setImageResource(R.drawable.arrow_highlighted);
}
private void updateForNormalState()
{
Resources r = App.get().getResources();
this.currentView.setBackgroundColor(r.getColor(R.color.white));
this.imgIcon.setImageResource(this.iconResource);
this.txtText.setTextColor(r.getColor(R.color.text_dark));
this.imgArrow.setImageResource(R.drawable.arrow);
}
}
Here is the layout file (xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#color/white"
android:gravity="center_vertical"
android:padding="5dp" >
<ImageView
android:id="#+id/img_menu_item_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="#drawable/info" />
<TextView
android:id="#+id/txt_menu_item_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24dp"
android:text="Menu item"
android:textColor="#color/text_dark"
android:layout_marginLeft="5dp" />
<ImageView
android:id="#+id/img_menu_item_arrow"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="#drawable/arrow" />
</LinearLayout>
After lots of experimenting finally this worked:
Every child view inside the list item layout must have android:duplicateParentState="true".
Then all of them can just use selector drawables. No extra effort inside the code is required.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/my_item_bg"
android:gravity="center_vertical"
android:padding="5dp" >
<ImageView
android:id="#+id/img_menu_item_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="#drawable/selector_info"
android:duplicateParentState="true" />
<TextView
android:id="#+id/txt_menu_item_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24dp"
android:text="Menu item"
android:textColor="#drawable/selector_color_my_button_text"
android:layout_marginLeft="5dp"
android:duplicateParentState="true" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="#drawable/selector_arrow"
android:duplicateParentState="true" />
</LinearLayout>
You should create custom drawable selectors, and set them as the background to your listview element.
Step#1, create another layout (named: layout_selected for this example), with the appropriate background color for your pressed state (like the layout file you supplied, but with the background attribute of the linear set to another color).
Then you will define a drawable selector, which will be placed in your drawable folder), defining which background should be use in which instance. This will look something like this:
<!-- pressed -->
<item android:drawable="#drawable/layout_selected" android:state_pressed="true"/>
<!-- focused -->
<item android:drawable="#drawable/layout_normal" android:state_focused="true"/>
<!-- default -->
<item android:drawable="#drawable/layout_normal"/>
Finally, to use this in your list, when you set the layout for your adapter, set it to the selector we just created, instead of your standard layout.
Maybe a little hard to explain, but you want to use 'Drawable Selectors' to accomplish what you want.
I would suggest to add ViewHolder pattern for listview. This will optimize your listview drawing & creating UI.
Also in that we can use setTag to save instance of row. In that you can handle touch event.
What i did so far is a list view of textviews having the normal text and clickable spans:
Clicking the span i'm opening the URL, clicking the item View around the textView leads to the listView OnItemClickListener navigating to the item details, that's fine:
Now the problem is:
touching the textView makes the normal text be kinda highlighted (with the same color it has when the item is selected completely), textView's OnTouchListener touch event fires but not OnFocusChangeListener event and the item's View does not get the selection style. Tried all the variations of FOCUS_BLOCK_DESCENDANTS for listView, item View, the textView focusable was enabled or disabled with the same result.
Fortunately, textView OnClickListener event fires this way, but that's so ugly: the text is invisible while the touch is not released as the selected text color is the same as the item color, there's no other indication that the user is going to the item details other than that ugly text vanishing.
I suspect that happens because the content of the textView is Spannable, and the parts which are not CliclableSpan-s behave in this strange way.
Any chance i could select the item once the normal text is touched ?
The listView item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:descendantFocusability="blocksDescendants"
android:orientation="horizontal" >
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:focusable="false" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:focusable="false"
android:text=""
android:textAppearance="?android:attr/textAppearanceLarge"
android:textStyle="bold" />
<TextView
android:id="#+id/info"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:focusable="false"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="#+id/details"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:focusable="false"
android:gravity="fill_horizontal|right"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
</LinearLayout>
With the text view setClickable(false) i'm able to disable this weird selection style in the way that nothing happens while touching the text view area, not good but might be useful for solution.
Also tried to add not focusable & not clickable button to each item, when it's touched the complete item is selected and when touch is released the item's click event is passed, that's exactly what i expected from the textView with Spannable content.
Did you try setting the background of your TextView to Android's default list_selector_background?
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setBackgroundResource(android.R.drawable.list_selector_background);
For me it seems to give the result that you want.
UPDATE: After seeing that the item is not just a single TextView
Well, this is not a perfect solution (since it's probably better to fix the TextView - ListView highlighting interaction somehow), but it works well enough.
I figured out that instead of setting the movement method on the TextView (that triggers the issue), it is just simpler to check in the ListView's onItemClick() (after a click is definitely confirmed) to see if we should launch the onClick() on our ClickableSpans:
public class MyActivity extends Activity {
private final Rect mLastTouch = new Rect();
private boolean spanClicked(ListView list, View view, int textViewId) {
final TextView widget = (TextView) view.findViewById(textViewId);
list.offsetRectIntoDescendantCoords(widget, mLastTouch);
int x = mLastTouch.right;
int y = mLastTouch.bottom;
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
final Layout layout = widget.getLayout();
final int line = layout.getLineForVertical(y);
final int off = layout.getOffsetForHorizontal(line, x);
final Editable buffer = widget.getEditableText();
final ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length == 0) return false;
link[0].onClick(widget);
return true;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (spanClicked(listView, view, R.id.details)) return;
// no span is clicked, normal onItemClick handling code here ..
}
});
listView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
mLastTouch.right = (int) event.getX();
mLastTouch.bottom = (int) event.getY();
}
return false;
}
});
// ...
}
}
The spanClicked() method is basically an abbreviated version of the LinkMovementMethod's onTouchEvent() method in the framework. To capture the last MotionEvent coordinates (to check for the click event), we simply add an OnTouchListener on our ListView.
Use TextView's setHighlightColor(Color.TRANSPARENT);
I think best way to solve this problem is using a selector. you can chan selection backgroun color so they will seen same
example selector code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:color="#000000" /> <!-- pressed -->
<item android:state_focused="true"
android:color="#000000" /> <!-- focused -->
<item android:color="#FFFFFF" /> <!-- default -->
</selector>
implement sth like that to your link.
let me know about result
Quote from documentation of the setMovementMethod() of TextView
Sets the movement method (arrow key handler) to be used for this
TextView. This can be null to disallow using the arrow keys to move
the cursor or scroll the view.
Be warned that if you want a TextView
with a key listener or movement method not to be focusable, or if you
want a TextView without a key listener or movement method to be
focusable, you must call android.view.View.setFocusable(boolean) again
after calling this to get the focusability back the way you want it.
The second paragraph explains that we should explicitly call the setFocusable method after setting the LinkMovementMethod to get focusability working the way we want.
You need to do it in code after inflating the list item.
Once you are able to get the focus, you can set the selector to have a different color text.
Here is the source code of setMovementMethod.
I have an item layout like this, and set the background by using item selector
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#drawable/itemselector"
android:orientation="horizontal" >
<CheckBox
android:id="#+id/message_row_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/message_row_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:textColor="#color/black" />
itemselector.xml :
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#color/yellow" />
<item
android:state_selected="true"
android:drawable="#color/green" />
<item
android:drawable="#color/white" />
</selector>
I have a ListView which will content some items. Then I used setOnItemClickListener() but it doesn't work. I found that the if I remove the checkbox in the item, everything will be okey.
What was the problem between the checkbox and the listener here?
Can you give me some solution?
Update : This is the code of listener
mainListView.setAdapter(messageAdapter);
mainListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Message p = (Message) arg0.getItemAtPosition(arg2);
Toast.makeText(TarsiusActivity.this, p.getTitle(), Toast.LENGTH_LONG);
Log.i("Item Clicked", p.getTitle());
}
});
ps: I want to make the inbox like gmail on android. Each row has a checkbox and user can click on item if they want to see the message
Best way to do this is set these following properties for your checkbox:
android:focusable="false"
android:focusableInTouchMode="false"
I had a same issue and did this.
The onItemClickListener for the listView will not work if you have any clickables like buttons, ImageButton, Checkbox, etc in the listView. Add
mainListView.setItemsCanFocus(true);
Refer ListView OnItemClickListener Not Responding?
Just add
android:descendantFocusability="blocksDescendants"
To your top level LinearLayout of the listitem.
You could add this code within your OnItemClickListener method:
public void onItemClick(AdapterView parent, View view, int position, long id){
CheckBox box = (CheckBox)view.findViewById(R.id.course_search_checkbox);
box.setChecked(true);
}
Use setOnCheckedChangeListener instead of onItemClickListner for checkbox
CheckBox check;
check=new CheckBox(this);
check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
}
});
I have CustomListView ,ie contain a background image and TextView,
When an item is selected i need to change the background image and font color, currently i can change the background of selected row of the listview using an xml, but i can't change the text color.
By default my text color is black when am clicking an item in listview i need to change the text color to white.
am using following layout for my customlistview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="29dp"
android:id="#+id/appcategoryLinearLayout"
android:background="#drawable/appcategorybg1"
android:gravity="left|center_vertical"
>
<TextView
android:gravity="left|center_vertical"
android:text="fdsfsdfsdfdsfdsfdsf"
android:paddingLeft="8dp"
android:textSize="8dp"
android:textColor="#color/black"
android:id="#+id/appCategoryNameTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
The only way to write your own ListAdapter and write custom controls which would have the visual properties you define.
I am not sure if this will help you but you can do some thing like this
Use TextView variables as global
TextView t ;
lv.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
if(t != null)
{
//reset the color to black
}
LinearLayout lay = (LinearLayout)v;
t = lay.getChildAt(0);
//now set text to bold
}
};