Highlight Custom Listview Item When Long Click

Highlight custom listview item when long click

using getActivity() is enough

setListAdapter(new CustomPasswordsList(getActivity(), titles));

You need to override onItemCheckedStateChanged

  public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
final int checkedCount = getListView().getCheckedItemCount();
// get checked items count

Drawing from the samples @

android-sdk-linux/samples/android-17/ApiDemos/src/com/example/android/apis/view/List16

Example : Modify the below according to your needs

public class MainActivity extends ListActivity {
String[] GENRES = new String[] {
"Action", "Adventure", "Animation", "Children", "Comedy",
"Documentary", "Drama",
"Foreign", "History", "Independent", "Romance", "Sci-Fi",
"Television", "Thriller"
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView lv = getListView();
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
lv.setMultiChoiceModeListener(new ModeCallback());
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_activated_1, GENRES));
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getActionBar().setSubtitle("Long press to start selection");
}

private class ModeCallback implements ListView.MultiChoiceModeListener {

public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.list_select_menu, menu);
mode.setTitle("Select Items");
return true;
}

public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}

public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.share:
Toast.makeText(MainActivity.this, "Shared " + getListView().getCheckedItemCount() +
" items", Toast.LENGTH_SHORT).show();
mode.finish();
break;
default:
Toast.makeText(MainActivity.this, "Clicked " + item.getTitle(),
Toast.LENGTH_SHORT).show();
break;
}
return true;
}

public void onDestroyActionMode(ActionMode mode) {
}

public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
final int checkedCount = getListView().getCheckedItemCount();
switch (checkedCount) {
case 0:
mode.setSubtitle(null);
break;
case 1:
mode.setSubtitle("One item selected");
break;
default:
mode.setSubtitle("" + checkedCount + " items selected");
break;
}
}

}
}

list_select_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/share"
android:title="share"
android:icon="@android:drawable/ic_menu_share"
android:showAsAction="always" />
</menu>

Snap shot

Sample Image

Since you are doubting whether it would work with custom adapter

Sample Image

Edit:

under res/values-v11/styles.xml

<resources>

<style name="AppTheme" parent="android:Theme.Holo.Light"></style>

<style name="activated" parent="AppTheme">
<item name="android:background">?android:attr/activatedBackgroundIndicator</item>
</style>

</resources>

In the custom layout for the root element add

 style="@style/activated"

Highlight effect while pressing item in custom ListView adapter

in your ListView XML, add:

 android:drawSelectorOnTop="true"

I also think you are using your adapter wrong...

Use the ViewHolder Pattern on your Adapter:

public class CustomCardSetsAdapter extends BaseAdapter {
List<Card> totalList;
ArrayList<Boolean> hiddenItems;
ListView parentLV;
Integer curPosition = -1;
public static int selectedRowIndex;

private class ViewHolderRow{
TextView cardName;
TextView manaCost;
ImageView setIcon;
}

public CustomCardSetsAdapter(CardSets cardList, ListView parentListView)
{
this.parentLV = parentListView;
assignSetValues(cardList);

totalList = cardList.getBlackrockMountain();
totalList.addAll(cardList.getClassic());
totalList.addAll(cardList.getCurseofNaxxramas());
totalList.addAll(cardList.getGoblinsvsGnomes());

Collections.sort(totalList,
new Comparator<Card>() {
public int compare(Card f1, Card f2) {
return f1.toString().compareTo(f2.toString());
}
});

hiddenItems = new ArrayList<>();

for (int i = 0; i < totalList.size(); i++) {
if(!totalList.get(i).getCollectible())
hiddenItems.add(true);
else
hiddenItems.add(false);
}
}

@Override
public int getCount() {
return (totalList.size() - getHiddenCount());
}

@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
final int index = getRealPosition(position);
ViewHolderRow theRow;
if(convertView == null) {
theRow = new ViewHolderRow();
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.card_list_item, parentLV, false);

// Cache your views
theRow.cardName = (TextView) convertView.findViewById(R.id.cardName);
theRow.manaCost = (TextView) convertView.findViewById(R.id.manaCost);
theRow.setIcon = (ImageView) convertView.findViewById(R.id.setIcon);

// Set the Tag to the ViewHolderRow
convertView.setTag(theRow);
}else{
// get the Row to re-use
theRow = (ViewHolderRow) convertView.getTag();
}

//... Removed convertView.setOnClickListener

Card curCard = totalList.get(index);

// Set Items
theRow.cardName.setText(curCard.getName());
setRarityColor(curCard,theRow.cardName);
theRow.manaCost.setText((curCard.getCost()).toString());
setSetIcon(curCard,theRow.setIcon);

if(position == curPosition){
convertView.setBackgroundColor(Color.WHITE);
}else{
convertView.setBackgroundColor(Color.TRANSPARENT);
}

return convertView;
}

@Override
public int getItemViewType(int position) {
return R.layout.card_list_item;
}

@Override
public int getViewTypeCount() {
return 1;
}

@Override
public boolean isEmpty() {
return false;
}

private int getHiddenCount()
{
int count = 0;
for(int i = 0;i <totalList.size();i++)
if(hiddenItems.get(i))
count++;
return count;
}

private int getRealPosition(int position) {
int hElements = getHiddenCountUpTo(position);
int diff = 0;
for(int i=0;i<hElements;i++) {
diff++;
if(hiddenItems.get(position+diff))
i--;
}
return (position + diff);
}

private int getHiddenCountUpTo(int location) {
int count = 0;
for(int i=0;i<=location;i++) {
if(hiddenItems.get(i))
count++;
}
return count;
}
}

Set an onListItemClickListener instead of using this on the entire convertView...

yourListView.setOnItemClickListener(ListListener);

private final OnItemClickListener ListListener = new OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
// ... Do something on click
}
}

How to highlight a ListView item using OnLongClickListener from custom Adapter class in Android

I finally managed to find a solution myself. I took a few different steps:

Code-related steps:

  1. I moved everything ActionMode related code from my adapter class to my activity class. Before that I triggered the action mode by using an OnLongClickListener on my TextView in my ListView item because at that point I didn't know how to make the TextView's text available for the ActionMode (I want to be able to delete it by clicking an icon in the ActionBar). When you use a CLickListener on one of the ListView items it kinda "blocks" the OnClickListener of the ListView item you set in your Activity. Don't do that!!!

  2. I set an OnItemLongClickListener to my ListView in my Activity. From there I trigger the ActionMode AND save the text from the item's TextView like this (itemNames is a List<String> set to my adapter, deleteString is a class attribute of my Activity):

    deleteString = itemNames.get(_postion);

But these steps were only to get my code working as it is supposed to due to the changes I had to make via XML.

XML-related steps:

  1. I had to remove the background attribute from my ListView item main layout
  2. I had to add the following attributes to my outer row layout: android:clickable="true" and android:longClickable="true" (maybe longClickable is already enough, just to be sure ;-) )
  3. I had to create an own selector drawable and set it as background to my ListView item layout: android:background="@drawable/my_selector"

This way I achieved the following:

  • I have a ListView in my Activity with a custom layout (TextView + CheckBox) and a custom adapter
  • I can use an OnCheckedChangeListener on the CheckBox
  • I can activate ActionMode by doing a long click on my ListView item AND reach the TextView's content for further processes
  • I get the default holo_blue_light background highlight on my ListView item when I click on it (I use Holo Theme Light with Dark Action Bar for my App)

The only thing that I didn't get to work via XML was to keep my ListView item highlighted while the ActionMode was active, so I did that by doing this

_view.setBackgroundResource(android.R.color.holo_blue_dark);

in the OnItemLongClickListener of my ListView in my Activity class (don't forget to redraw or refresh your ListView in onDestroyActionMode(ActionMode _mode) of your ActionMode.Callback)

Voilà! I hope this might help some of you! Took me a few days and LOTS of research.

Here my code examples for my ListView item layout and my selector layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_selector"
android:clickable="true"
android:longClickable="true" >

<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="6dp" >
</CheckBox>

<TextView
android:id="@+id/shoppingListItemName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:layout_toLeftOf="@id/checkBox"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textIsSelectable="true" >
</TextView>

</RelativeLayout>

My selector:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true">
<layer-list>
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/holo_blue_light" />
</shape>
</item>
</layer-list>
</item>
<item>
<color android:color="#00000000" />
</item>

</selector>

Android - Keep ListView's item highlighted once one has been clicked

Put a position variable for selected item. Change the position in onItemClicked() method. Check the selected position in List Adapter inside getView() and set the background for the selected item.

public class TestAdapter extends BaseAdapter
{
private Context context;
private ArrayList<TestList> testList;
private int selectedIndex;
private int selectedColor = Color.parseColor("#1b1b1b");

public TestAdapter(Context ctx, ArrayList<TestList> testList)
{
this.context = ctx;
this.testList = testList;
selectedIndex = -1;
}

public void setSelectedIndex(int ind)
{
selectedIndex = ind;
notifyDataSetChanged();
}

@Override
public int getCount()
{
return testList.size();
}

@Override
public Object getItem(int position)
{
return testList.get(position);
}

@Override
public long getItemId(int position)
{
return position;
}

private class ViewHolder
{
TextView tv;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View vi = convertView;
ViewHolder holder;
if(convertView == null)
{
vi = LayoutInflater.from(context).inflate(R.layout.test_list_item, null);
holder = new ViewHolder();

holder.tv = (TextView) vi;

vi.setTag(holder);
}
else
{
holder = (ViewHolder) vi.getTag();
}

if(selectedIndex!= -1 && position == selectedIndex)
{
holder.tv.setBackgroundColor(Color.BLACK);
}
else
{
holder.tv.setBackgroundColor(selectedColor);
}
holder.tv.setText("" + (position + 1) + " " + testList.get(position).getTestText());

return vi;
}

}

Now set the selectedIndex variable when a list item clicked.

public class TestActivity extends Activity implements OnItemClickListener
{
// Implemented onItemClickListener

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.setSelectedIndex(position);
}
}

How to highlight ListView-Items

You should use a Selector.

This question and its answer might help....

How to select an ListView item after long click?

It's possible, but just barely... I actually don't know how such a simple thing can wind up so ridiculously complicated.

The key to the answer can be found here: Android: keep blue background after ListView selection

What this boils down to is to define an additional style that is used by the ListView and setting the choice mode to AbsListView.CHOICE_MODE_SINGLE (as explained in the linked answer).

This allows you programmatically toggle the selection using Listview.setItemChecked(). However, you need to keep track of the index of the touched item in the onItemLongClick callback yourself, because ListView.setSelection() won't do that (at least ListView.getSelectedItem() will always return -1 as far as I can see).

Code (for simplicity, my fragment implements all three OnItemClickListener, OnItemLongClickListener, and
ActionMode.Callback):

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
this.listViewAdapter = new ListViewAdapter();
this.root = (ListView)inflater.inflate(R.layout.fragment_bookmarks, container, false);
this.root.setAdapter(this.listViewAdapter);
this.root.setOnItemClickListener(this);
this.root.setOnItemLongClickListener(this);
this.root.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
return this.root;
}

@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if(this.cabMode != null)
return false;
this.selectedPosition = position;
this.root.setItemChecked(position, true);

this.root.setOnItemClickListener(null);
this.cabMode = getActivity().startActionMode(this);
return true;
}

And finally, if you want to get rid of the selection when the CAB is closed:

@Override
public void onDestroyActionMode(ActionMode mode) {
cabMode = null;
this.root.setItemChecked(this.selectedPosition, false);
this.selectedPosition = -1;
this.root.setOnItemClickListener(this);
}

Registering and unregistering the OnItemClickListener makes sure that while the CAB is active you won't accidentally trigger the action usually associated with the item (like opening a detail view).

highlighting selected item in custom list view using context menu?

@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked)
{
try
{
final int checkedCount = listView.getCheckedItemCount();
mode.setTitle(""+checkedCount);

if (checked)
{
adapter.setNewSelection(position, checked);
}
else
{
adapter.removeSelection(position);
}
adapter.notifyDataSetChanged();
}
catch (Exception e)
{
e.printStackTrace();
}
}

add these methods in your adapter class

private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
public void setNewSelection(int position, boolean value)
{
mSelection.put(position, value);
}

public boolean isPositionChecked(int position)
{
Boolean result = mSelection.get(position);
return result == null ? false : result;
}

public Set<Integer> getCurrentCheckedPosition() {
return mSelection.keySet();
}

public void removeSelection(int position) {
mSelection.remove(position);
}

public void clearSelection() {
mSelection = new HashMap<Integer, Boolean>();
}

call this method inside getView() method of adapter it works properly

convertView.setBackgroundColor(mContext.getResources().getColor(android.R.color.transparent));
if (mSelection.get(position) != null)
{
convertView.setBackgroundColor(mContext.getResources().getColor(R.color.message_selector_holo_blue));
}

Highlight multiple items of ListView

Okay the problem is solved while doing some experiments with different ways suggested on SO.

Here is what I did to get what I wanted

Added this to my Relative Layout where I defined layout of ListView
Item.

<RelativeLayout
...
android:background="@drawable/rowbgselector">

Created a new resource file in drawable folder

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true"
android:drawable="@android:color/darker_gray"/>
</selector>

That's all I did to get the required result.



Related Topics



Leave a reply



Submit