programacion - manual android studio avanzado
Android: mantenga el elemento de ListView resaltado una vez que se ha hecho clic en uno (11)
Así que tengo una actividad con 2 widgets ListView
, cuando seleccionas un valor en el primero, el segundo se rellena con valores relacionados con la selección en el primer ListView
. Esta mecánica funciona sin problemas, pero ahora quiero que las opciones del usuario permanezcan resaltadas. He leído una buena cantidad de preguntas relacionadas con este tema y parece que hay una gran cantidad de formas en que uno puede lograr esto, pero después de probar unas 4 o 5 de ellas todavía no puedo lograr que funcione.
Lo tengo trabajando en el segundo ListView
usando el android:listSelector="#CCCCCC"
Atributo XML, pero parece que se borró una vez que se introdujo un OnItemClickListener
en la mezcla (como el que uso en mi primer ListView
).
Hasta ahora, esto es lo que tengo:
Custom OnItemClickListener
Encontré varias respuestas sobre este tema (lo modifiqué ligeramente para que cargue mi información en el segundo ListView):
private class ItemHighlighterListener implements OnItemClickListener {
private View oldSelection = null;
public void clearSelection() {
if(oldSelection != null) {
oldSelection.setBackgroundColor(android.R.color.transparent);
}
}
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
clearSelection();
oldSelection = view;
view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.list_selector));
loadClubs(mXMLPortalOptions.getRegion(pos).getId());
mClubList.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.list_item_white, mClubs));
}
}
Aquí está mi archivo list_selector.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"><shape>
<solid android:color="#CCCCCC" />
</shape></item>
<item android:state_selected="false"><shape>
<solid android:color="#FFFFFF" />
</shape></item>
</selector>
El método (OnItemClick) se llama y se ejecuta, pero el fondo de mi ListItem
permanece del mismo color: /
No puedo creer que esta simple tarea haya resultado tan complicada.
Si he omitido el código que podría ser útil o si mi pregunta carece de detalles, siéntase libre de señalarlo y haré todo lo posible para explicarme.
Coloque una variable de posición para el elemento seleccionado. Cambie la posición en el método onItemClicked()
. Compruebe la posición seleccionada en List Adapter dentro de getView()
y configure el fondo para el elemento seleccionado.
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;
}
}
Ahora configure la variable selectedIndex cuando se hace clic en un elemento de la lista.
public class TestActivity extends Activity implements OnItemClickListener
{
// Implemented onItemClickListener
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.setSelectedIndex(position);
}
}
Creo que la mejor y más fácil solución es esta. No necesita configurar ningún android:listSelector
en el ListView o hacer ningún cambio en el adaptador. Ni siquiera necesita llamar a setSelection(position)
en OnItemClickListener
ya que se maneja automáticamente.
Establecer en su ListView:
android:choiceMode="singleChoice"
Establecer el fondo del elemento de la lista en sí:
android:background="?android:attr/activatedBackgroundIndicator"
Eso es.
De esta forma obtendrás un comportamiento predeterminado del sistema. Así es como se hace en el diseño predeterminado de android.R.layout.simple_list_item_activated_1
.
Hay una solución completamente XML completa, que funcionó para mí. En primer lugar, defina XML-drawable con el código del selector en el que el estado "normal" corresponderá al estado visual "seleccionado sin comprimir" de un elemento de la lista, y el state_pressed = verdadero al estado visual "presionado". Ejemplo del archivo "custom_item_selector.xml", que se asemeja a la selección Holo blue:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid
android:color="#643292ff">
</solid>
<stroke
android:width="1dp"
android:color="#c83292ff">
</stroke>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid
android:color="#323292ff">
</solid>
<stroke
android:width="1dp"
android:color="#783292ff">
</stroke>
</shape>
</item>
</selector>
(también puede establecer el estado enfocado allí). En segundo lugar, aplique este xml-drawable como ListSegs listSelector y configure su choiceMode deseado:
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:choiceMode="singleChoice"
android:listSelector="@drawable/custom_item_selector"/>
Eso es todo. Permite definir diferentes estados visuales para elementos "simplemente seleccionados" y "seleccionados por presión", por ejemplo, haciendo que los elementos sean más brillantes en la prensa.
Lo estaba buscando hace dos semanas y el resultado es que no es posible con un selector dibujable. Para obtener más información, lea esta publicación en Android Developers Blog: android-developers.blogspot.com/2008/12/touch-mode.html
En resumen: solo cuando su dedo está en la pantalla, se selecciona el elemento.
Otra posibilidad es guardar qué elemento se selecciona en var y pintar diferente usando su adaptador personalizado como dice Shaiful.
Me enfrenté a un problema similar. Esa es mi solución:
Primero agrega selector de lista personalizado a tu vista de lista:
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:listSelector="@drawable/listselector" />
Dentro de listselector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_accelerated="false"
android:drawable="@drawable/bg" />
</selector>
Y finalmente un bg.xml dibujable con el color de su destaque:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#33b5e6"/>
</shape>
Para ampliar la gran solución de Shaiful, es posible que no hagas que la suya funcione en tu situación.
Si está utilizando tenga su código todo en public void onListItemClick(ListView l, View v, int index, long id)
, si está utilizando fragmentos y tiene que declarar una interfaz en lugar de implementar OnListItemClickListener, o lo que sea que está causando su IDE generar errores, es posible que tenga que acceder a variables y métodos estáticamente.
public static int selectedPosition = 0;
ArrayAdapter<Your_obj> adapter = null;
@Override
public void onListItemClick(ListView l, View v, int index, long id) {
super.onListItemClick(l, v, index, id);
selectedPosition = index;
Your_adapter.setSelectedIndex(selectedPosition);
adapter.notifyDataSetChanged();
}
Y en Your_adapter:
private static int selectedIndex;
//public Your_adapter...
public static void setSelectedIndex(int ind) {
selectedIndex = ind;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
WellHolder holder = null;
if (null == convertView) {
//set up your "holder"
}
if (position == selectedIndex) {
convertView.setBackgroundColor(convertView.getResources().getColor(R.color.cyan));
}
else {
convertView.setBackgroundColor(convertView.getResources().getColor(R.color.silver));
}
return convertView;
}
Algunas otras diferencias son que no tiene que inicializar ninguna variable como "0" o "-1" y se llama a notifyDataSetChanged () en su actividad.
Una vez más, gracias por tu solución @Shaiful. Ciertamente me ayudó a ahorrar tiempo tratando de obtener lo que está predeterminado en iOS para trabajar con Android, todo mientras evito selector / item / focused / pressed / etc.
Para mantener los elementos de la lista (selección múltiple) resaltados, al hacer clic (activar), siga los pasos.
1. Configure el fondo para mostrar el diseño del elemento como dibujable.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/list_item_selector">
<ImageView
android:id="@+id/icon"
android:layout_width="22px"
android:layout_height="22px"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="@mipmap/ic_launcher" >
</ImageView>
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@+id/label"
android:textSize="20px" >
</TextView>
</LinearLayout>
2. selector dibujable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@android:color/holo_red_light" />
<item android:state_activated="true" android:drawable="@android:color/holo_orange_dark" />
</selector>
3. Listview establece el modo de elección múltiple
getListView (). setChoiceMode (ListView.CHOICE_MODE_MULTIPLE);
Debajo de la imagen se muestra, cuando el usuario seleccionó varios elementos de la lista.
Para resumir esta publicación y tal vez ayudar a otra persona en el futuro, sugiero la respuesta :)
Primero, necesitamos crear el archivo res/drawable/list_item_background.xml
con los siguientes contenidos:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_activated="true"
android:drawable="@color/list_item_activated" />
<item
android:drawable="@color/list_item_default" />
</selector>
Especifique sus recursos dibujables, por supuesto. Y también puede agregar otros <item>
con diferentes estados como state_pressed
, state_focused
, etc.
Entonces, debemos establecer el parámetro de background
para nuestro elemento de lista personalizado elemento ViewGroup
( ViewGroup
res/layout/list_item_layout.xml
) de esta manera:
android:background="@drawable/list_item_background"
El siguiente paso es modificar nuestra clase Adapter
personalizada. Aquí está el siguiente fragmento de código:
public class CustomAdapter extends BaseAdapter {
private List<Item> items;
private LayoutInflater itemInflater;
private int selectedIndex; // add this
public CustomAdapter(Context c, List<Item> items) {
this.items = items;
this.itemInflater = LayoutInflater.from(c);
selectedIndex = -1; // add this
}
/* add this */
public void setSelectedIndex(int index) {
selectedIndex = index;
notifyDataSetChanged();
}
/* other adapter''s stuff */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = itemInflater.inflate(R.layout.list_item_layout, parent, false);
}
// add this
convertView.setActivated(selectedIndex != -1 && position == selectedIndex);
/* do some stuff */
return convertView;
}
}
Finalmente, deberíamos llamar al método del adaptador setSelectedIndex(position)
el método onItemClick(...)
de AdapterView.OnItemClickListener
.
public class YourActivity extends Activity
implements AdapterView.OnItemClickListener {
private CustomAdapter mCustomAdapter;
/* activity implementation */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mCustomAdapter.setSelectedIndex(position);
}
}
Ahora, podemos estar satisfechos con los elementos de la lista adecuada destacando :)
PD: si queremos habilitar el modo de opción múltiple en nuestra lista, listView
la siguiente cadena en nuestra clase de actividad donde se listView
instancia de listView
:
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Por lo tanto, obtendremos los elementos múltiples adecuados resaltados.
- Espero que esto ayude a cualquiera :)
Si puede usar un drawable para mostrar listItem Highlighted, entonces debe usar el siguiente código:
listView.setSelector(R.drawable.bg_image);
Funciona.
lv.setSelector(R.drawable.highlighter);
poner una imagen highlighter.png
en una carpeta dibujable
forma más sencilla de resaltar el elemento seleccionado en la vista de lista.
//create a list_itemselectorin drawable folder
//you will get the list item selected background color change once you select //the item
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Focused State -->
<item android:state_focused="true"><shape>
<solid android:color="#66FFFFFF" />
</shape></item>
<!-- Pressed State -->
<item android:state_pressed="true"><shape>
<solid android:color="@color/Black" />
</shape></item>
<!-- Default State -->
<item><shape>
<solid android:color="@color/Black" />
</shape></item>
</selector>
//create a list in layout folder
<ListView
android:id="@+id/mySlidingList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:divider="@color/GrayHot"
android:dividerHeight="1dip"
android:listSelector="@drawable/list_itemselector"
android:scrollbars="none" />
// Y ver la salida.