HorizontalListview with image select and unselect - android

i am getting problem in image select/unselect in listiview.
in my case,
ByDefault->image color(Yellow)
First click->image color(Orange)
Second click->image color(Yellow)
If user click on over way then perfect,but when user first time click on first image and second time click on second image then both image color is orange(that's problem).
In my case only one image color is orange(means selected) at a time.

If you only support HoneyComb and above, it'll easy. Create a StateListDrawable and set it to list view item's background.
selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="#drawable/item_focus" />
<item android:drawable="#android:color/transparent" />
</selector>
listview item's layout
<ImageView
android:id="#+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:padding="5dp" />
and the last, set your listview choice mode to SINGLE
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
2. If you manage to support pre HoneyComb, you will have to write your own layout implement checkable. You do this in order to work-out using checked state. Let take an example with LinearLayout(you can do the same with others).
package com.example.listviewactivestate;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Checkable;
import android.widget.LinearLayout;
public class CustomLinearLayout extends LinearLayout implements Checkable {
private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
private boolean checked = false;
public CustomLinearLayout (Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomLinearLayout (Context context) {
super(context);
}
#Override
public boolean isChecked() {
return checked;
}
#Override
public void setChecked(boolean checked) {
this.checked = checked;
refreshDrawableState();
// Propagate to childs
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child instanceof Checkable) {
((Checkable) child).setChecked(checked);
}
}
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
#Override
public void toggle() {
this.checked = !this.checked;
}
}
Use this custom view in xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.listviewactivestate.CustomLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/selector"
>
<ImageView
android:id="#+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:padding="5dp" />
</com.example.listviewactivestate.CustomLinearLayout >
Change state_activated to state_checked
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#drawable/item_focus" />
<item android:drawable="#android:color/transparent" />
</selector>
Also set listview choice mode to SINGLE. If it does not work, add onItemClickEvent like this
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
list.setItemChecked(position, true);//make sure click item is set to checked.
}
});

Related

Android ListView selection background

Okay I'm going absolutely nuts with this. I have a ListView in mode singleChoice, when I click on it I set it to selected. And I set the background to a drawable with a selector (and I tried many states that could correspond to a selected item). However when I select it the background doesn't change and I dont get why. I visited dozens of forums for this but couldn't get an answer. Here's my code:
The ListView in my activity:
<com.gaetanl.aspa.ui.component.ExtensibleListView
android:id="#+id/payment_billing_address_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/item_selectable"
android:choiceMode="singleChoice"></com.gaetanl.aspa.ui.component.ExtensibleListView>
Its class:
public class ExtensibleListView extends ListView {
public ExtensibleListView(Context context) {
this(context, null);
}
public ExtensibleListView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.listViewStyle);
}
public ExtensibleListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(this, "item " + position + " selected = " + view.isSelected());
view.setSelected(true);
Log.d(this, "selected = " + view.isSelected());
}
});
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
The selector:
<?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/colorPrimary" />
<item
android:state_active="true"
android:drawable="#color/colorPrimary" />
<item
android:state_checked="true"
android:drawable="#color/colorPrimary" />
<item
android:state_selected="true"
android:drawable="#color/colorPrimary" />
<item
android:drawable="#android:color/transparent" />
</selector>
Method I:
In your list adapter,create getter and setter methods for position.Then in getView method, compare the position as in below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item.xml, null);
holder = new ViewHolder(); holder.itemLayout(LinearLyout)convertView.findViewById(R.id.item_layout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if(position==getPosition()){
holder.itemLayout.setBackgroundColor(ContextCompat.getColor(context,R.color.back_ground_color));
}else{
holder.itemLayout.setBackgroundColor(ContextCompat.getColor(context,R.color.background_unselect));
}
return convertView;
}
public void setPosition(int posit) {
this.position = posit;
}
private int getPosition() {
return this.position;
}
Then in the activity , inside listView's onItemSelected() method: call the adapter's setPositionMethod:
list_view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
mAdapter.setPosition(i);
mAdapter.notifyDataSetChanged();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
Just set the list selector to transparent ..that should do the job.
Method II:
Or may be ,You need a selector like below:
<?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/color_primary" >
</item>
<item
android:state_focused="true"
android:drawable="#color/color_primary" >
</item>
<item
android:state_selected="true"
android:drawablecolor="#color/color_primary" >
</item>
<item android:color="#color/#color/transparent" >
</item>
</selector>
then put list selector as #drawable/list_selector
But, if that doesn't work then I think you can set the background of item xml layout as
android:background="#drawable/list_selector"
Okay I found the answer. I was stupidly trying to set the ListView background (see code above). What I needed to do was, when creating adapter, to select a view for the items that incorporates variation for selected items. Android has one by default: simple_list_item_single_choice.
So here's the working code:
myListView = ((ListView) findViewById(R.id.listview_id));
ArrayAdapter<String> myAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_single_choice, myList);
myListView.setAdapter(myAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setSelected(true);
}
});
And then you have it, a list view with radio buttons on the right that check themselves when you click on em.
And here's the ListView in my layout.xml:
<ListView
android:id="#+id/listview_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice">
</ListView>

Add border to ImageView inside GridView

How do I add a border to an ImageView inside a GridView after clicking on an image and disappear border if again clicked on the same image again?
gv_gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long Id) {
// TODO Auto-generated method stub
Toast.makeText(getBaseContext(),"You clikced on "+position,Toast.LENGTH_SHORT ).show();
// gv_gridview.setSelected(true);
// gv_gridview.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
// gv_gridview.setDrawSelectorOnTop(true);
}
});
This is grid item selection problem
I assume that your grid item is an ImageView.
Solution
Find working example project here: https://github.com/jskierbi/sample-gridview-select
You need to add CheckedImageView class to your project, so grid view can check the items for you.
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.ImageView;
public class CheckedImageView extends ImageView implements Checkable {
boolean mFlgChecked = false;
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
public CheckedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
#Override
public boolean isChecked() {
return mFlgChecked;
}
#Override
public void setChecked(boolean checked) {
mFlgChecked = checked;
refreshDrawableState();
}
#Override
public void toggle() {
mFlgChecked = !mFlgChecked;
}
}
2. Add colors (res/values/colors.xml):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="image_selected">#0000FF</color>
<color name="transparent">#00000000</color>
</resources>
Add selector, this will define which color is used for which state of your image (res/drawable/checked_image.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#color/image_selected" />
<item android:drawable="#color/transparent" />
</selector>
Add grid item layout (res/layout/grid_view_item.xml)
Remember to change com.example.CheckedImageView package name so it reflects where you put your CheckedImageView class.
<?xml version="1.0" encoding="utf-8"?>
<com.example.CheckedImageView android:id="#+id/image"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/checked_image"
android:cropToPadding="true"
android:padding="6dp" />
And finally, use this layout in adapter. Below is full code for my Activity class:
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
public class MainActivity extends Activity {
private static final #DrawableRes int[] IMAGES = {
R.drawable.a001, R.drawable.a002, R.drawable.a003, R.drawable.a004, R.drawable.a005,
R.drawable.a006, R.drawable.a007, R.drawable.a008, R.drawable.a009, R.drawable.a010,
R.drawable.a011, R.drawable.a012, R.drawable.a013, R.drawable.a014, R.drawable.a015,
R.drawable.a016, R.drawable.a017, R.drawable.a018
};
private GridView mGridView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGridView = ((GridView) findViewById(R.id.gridview));
mGridView.setChoiceMode(GridView.CHOICE_MODE_SINGLE);
mGridView.setAdapter(new BaseAdapter() {
#Override public int getCount() {
return IMAGES.length;
}
#Override public Object getItem(int position) {
return IMAGES[position];
}
#Override public long getItemId(int position) {
return IMAGES[position];
}
#Override public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null || !(convertView instanceof ImageView)) {
ImageView imageView = (ImageView) getLayoutInflater().inflate(R.layout.grid_view_item, parent, false);
imageView.setImageResource(IMAGES[position]);
convertView = imageView;
}
return convertView;
}
});
}
}
Finally, you can use mGridView.getCheckedItemPosition() to get position of checked item.
Screen:
Not sure if this is what you are looking for but you can try the following...
In Your <GridView> Tag
android:horizontalSpacing="1dp"
android:verticalSpacing="1dp"

Navigation drawer selector disable not working

I need to disable the second element in my navigation drawer until a certain task is finished. Here is how I disable the second element:
nav_item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/dark_green"
android:state_pressed="true" />
<item android:drawable="#android:color/transparent"
android:state_enabled="true" />
<item android:drawable="#android:color/darker_gray"
android:state_enabled="false" />
</selector>
nav_fragment.xml (wrapped in a DrawerLayout)
<ListView
android:id="#+id/left_drawer"
android:layout_width="#dimen/nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:cacheColorHint="#0000"
android:background="#drawable/gradient_radial_backround"
android:choiceMode="singleChoice"
android:divider="#color/green_light"
android:dividerHeight="1dp" />
nav_list_item.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/nav_list_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/nav_item_selector"
android:orientation="horizontal"
android:padding="#dimen/standard_padding">
<ImageView
android:id="#+id/nav_list_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#null"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/nav_list_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="sans-serif-light"
android:gravity="center_vertical"
android:minHeight="#dimen/listPreferredItemHeightSmall"
android:paddingLeft="#dimen/activity_horizontal_small_margin"
android:text="List Item"
android:textSize="#dimen/text_nav_list_entry"
android:textColor="#color/dark_green" />
</LinearLayout>
Activity:
public class NavItemAdapter extends ArrayAdapter<String> {
LayoutInflater inflater;
private String[] listItems;
public NavItemAdapter(Context context, int textViewResourceId, String[] listItems) {
super(context, textViewResourceId, listItems);
this.listItems = listItems;
inflater = LayoutInflater.from(context);
}
#Override
public boolean isEnabled(int position)
{
if(position == 1)
return false;
else
return true;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = new NavItemView(getContext());
NavItemView navItemView = (NavItemView) convertView;
switch (position) {
case 0:
navItemView.setUpItem(R.drawable.ic_nav_1_checked, listItems[position], R.drawable.ic_nav_1);
break;
case 1:
navItemView.setUpItem(R.drawable.ic_nav_2_checked, listItems[position], R.drawable.ic_nav_2);
break;
case 2:
navItemView.setUpItem(R.drawable.ic_nav_3_checked, listItems[position], R.drawable.ic_nav_3);
break;
case 3:
navItemView.setUpItem(R.drawable.ic_nav_4_checked, listItems[position], R.drawable.ic_nav_4);
break;
case 4:
navItemView.setUpItem(R.drawable.ic_nav_5_checked, listItems[position], R.drawable.ic_nav_5);
break;
case 5:
navItemView.setUpItem(R.drawable.ic_nav_6_checked, listItems[position], R.drawable.ic_nav_6);
break;
}
return convertView;
}
}
class NavItemView extends LinearLayout implements Checkable {
private View v;
private ImageView iconView;
private TextView textView;
private Boolean checked = false;
private int mImageChecked;
private int mImage;
public NavItemView(Context context) {
super(context);
LayoutInflater inflater = LayoutInflater.from(context);
v = inflater.inflate(R.layout.list_item_navdrawer, this, true);
assert v != null;
iconView = (ImageView) v.findViewById(R.id.nav_list_icon);
textView = (TextView) v.findViewById(R.id.nav_list_text);
}
#Override
public boolean isChecked() {
return checked;
}
#Override
public void setChecked(boolean checked) {
this.checked = checked;
if (isChecked()) {
setBackgroundColor(getResources().getColor(R.color.transparent));
textView.setTextColor(getResources().getColor(R.color.light_pink));
iconView.setImageResource(mImageChecked);
} else {
//Reset to default
setBackgroundColor(getResources().getColor(R.color.transparent));
textView.setTextColor(getResources().getColor(R.color.green_lighter));
iconView.setImageResource(mImage);
}
}
#Override
public void toggle() {
checked = !checked;
}
private void setUpItem(int imageChecked, String title, int image) {
mImageChecked = imageChecked;
mImage = image;
textView.setText(title);
iconView.setImageResource(image);
}
}
What happens is the item is disabled, but the selector does not kick in (it stays the same colour). Not only that but that item's divider disappears which is even worse! What is happening here?
I actually can't believe this but the only solution seems to be a bit of a weird hack. There are several threads on this question but the only solid answer I've found is from user Jason Lin located here.
It seems there were two pieces of the puzzle missing, the first is that returning false for the item I want to disable in isEnabled() merely makes the item unclickable and unfocusable. To actually disable it I need to perform the same check in getView() and call setEnabled(false) on the item...
if(position == 1)
convertView.setEnabled(false);
AND
Set android:duplicateParentState="true" on the linear layout of the row.
This was the most important part as obviously I tried to called setEnabled(false) in getView() first of all, but it took me all day to learn I need the combination of all 3 of these things - returning false in isEnabled(), setting enabled to false in getView(), and setting duplicateParentState to true :)

setItemChecked not working on Gingerbread

I am using the following selector to change the appearance of text in a listView item:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
android:color="#FFFFFFFF" /> <!-- checked -->
<item android:state_activated="true"
android:color="#FFFFFFFF" /> <!-- activated -->
<item android:state_pressed="true"
android:color="#FFFFFFFF" /> <!-- pressed -->
<item android:state_focused="true"
android:color="#FFFFFFFF" /> <!-- focused -->
<item android:color="#FF000000" /> <!-- default -->
</selector>
The entire selector works fine on later versions of Android (ICS, JB), but on Gingerbread, while the pressed_state item is being applied correctly, when I call setItemChecked on the listView, the state_checked item isn't applied.
The code I am using to set the item is as follows:
#Override
protected void onResume()
{
super.onResume();
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
for (int index = 0; index < measureList.size(); index++)
{
if (measureList.get(index).getId() == appContext.getMeasureId())
{
getListView().setItemChecked(index, true);
}
}
}
and the xml used to set the selector is this:
<TextView
android:id="#+id/item_text"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:paddingRight="10dp"
android:ellipsize="end"
android:layout_toRightOf="#id/item_thumb"
android:maxLines="1"
android:scrollHorizontally="true"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="#color/selected_text_selector"
/>
Does anyone know why this happens? I haven't yet tested it out on versions of Android between GB and ICS, but will edit this post as soon as I do.
After a little searching, it seems to me the reason that the state_checked isn't expressed pre-Honeycomb is the fact that the setActive method on View is not available before API level 11. This means that the checked state is not propagated to the child views of my layout.
THE KEY:
Swap the TextView for a CheckedTextView
Propagate the checked state from the parent view to the children
1) Was a simple switch in the XML, and for 2) I modified the code in the answer linked to by Voicu to give the following:
public class CheckableRelativeLayout extends RelativeLayout implements Checkable
{
private boolean checked = false;
public CheckableRelativeLayout(Context context) {
super(context, null);
}
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
private static final int[] CheckedStateSet = {
R.attr.state_checked
};
#Override
protected void dispatchSetPressed(boolean pressed)
{
super.dispatchSetPressed(pressed);
setChecked(pressed);
}
#Override
public void setChecked(boolean checked) {
this.checked = checked;
for (int index = 0; index < getChildCount(); index++)
{
View view = getChildAt(index);
if (view.getClass().toString().equals(CheckedTextView.class.toString()))
{
CheckedTextView checkable = (CheckedTextView)view;
checkable.setChecked(checked);
checkable.refreshDrawableState();
}
}
refreshDrawableState();
}
public boolean isChecked() {
return checked;
}
public void toggle() {
checked = !checked;
refreshDrawableState();
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CheckedStateSet);
}
return drawableState;
}
#Override
public boolean performClick() {
return super.performClick();
}
}

Change expandable indicator in ExpandableListView

Trying to create an ExpandableListView. The initial view with the groups shows up fine. However, when I click the list item, my arrow does not change. See the images below.
How can I change the arrow's direction?
The layout XML:
<ExpandableListView
android:id="#+id/expandable_list"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:divider="#null"
android:background="#ffffff"
android:groupIndicator="#drawable/settings_selector"
android:transcriptMode="alwaysScroll" />
settings_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="#drawable/arrow_down"
android:state_empty="true"/>
<item
android:drawable="#drawable/arrow_right"
android:state_expanded="true"/>
</selector>
</animation-list>
expandable listview
<ExpandableListView
android:id="#+id/expandable_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:groupIndicator="#drawable/group_indicator"
android:transcriptMode="alwaysScroll" />
setindicator here iam useing setindicator code like this this working nice
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
mExpandableList = (ExpandableListView)findViewById(R.id.expandable_list);
mExpandableList.setIndicatorBounds(width - GetPixelFromDips(50), width - GetPixelFromDips(10));
public int GetPixelFromDips(float pixels) {
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
return (int) (pixels * scale + 0.5f);
}
res/drawable/group_indicator
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">    
<item android:drawable="#drawable/arrow_right" android:state_empty="true"> </item>    
<item android:drawable="#drawable/arrow_down" android:state_expanded="true"></item>     
<item android:drawable="#drawable/arrow_right"></item>
</selector>
Try that for your settings_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="#drawable/arrow_right"
android:state_expanded="true" />
<item
android:drawable="#drawable/arrow_down" />
</selector>
I had gone the way below: decide the left/right drawable for your groupView based on isExpanded flag.
By that way, it is easier for us to customize the padding/background and other things of the indicator drawable.
Hope it helps.
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
TextView textView = (TextView) mLayoutInflater.inflate(R.layout.menu_group, null);
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, isExpanded ? 0 : android.R.drawable.ic_menu_more, 0);
textView.setText(getGroup(groupPosition).toString());
return textView;
}
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;
public class MyActivity extends Activity {
private ExpandableListView mExpandableList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mExpandableList = (ExpandableListView)findViewById(R.id.expandable_list);
mExpandableList.setGroupIndicator(null);
ArrayList<Parent> arrayParents = new ArrayList<Parent>();
ArrayList<String> arrayChildren = new ArrayList<String>();
//here we set the parents and the children
for (int i = 0; i < 10; i++){
//for each "i" create a new Parent object to set the title and the children
Parent parent = new Parent();
parent.setTitle("Parent " + i);
arrayChildren = new ArrayList<String>();
for (int j = 0; j < 10; j++) {
arrayChildren.add("Child " + j);
}
parent.setArrayChildren(arrayChildren);
//in this array we add the Parent object. We will use the arrayParents at the setAdapter
arrayParents.add(parent);
}
//sets the adapter that provides data to the list.
mExpandableList.setAdapter(new MyCustomAdapter(MyActivity.this,arrayParents));
}
public class Parent {
private String mTitle;
private ArrayList<String> mArrayChildren;
public String getTitle() {
return mTitle;
}
public void setTitle(String mTitle) {
this.mTitle = mTitle;
}
public ArrayList<String> getArrayChildren() {
return mArrayChildren;
}
public void setArrayChildren(ArrayList<String> mArrayChildren) {
this.mArrayChildren = mArrayChildren;
}
}
public class MyCustomAdapter extends BaseExpandableListAdapter implements OnClickListener{
private LayoutInflater inflater;
private ArrayList<Parent> mParent;
public MyCustomAdapter(Context context, ArrayList<Parent> parent){
mParent = parent;
inflater = LayoutInflater.from(context);
}
#Override
//counts the number of group/parent items so the list knows how many times calls getGroupView() method
public int getGroupCount() {
return mParent.size();
}
#Override
//counts the number of children items so the list knows how many times calls getChildView() method
public int getChildrenCount(int i) {
return mParent.get(i).getArrayChildren().size();
}
#Override
//gets the title of each parent/group
public Object getGroup(int i) {
return mParent.get(i).getTitle();
}
#Override
//gets the name of each item
public Object getChild(int i, int i1) {
return mParent.get(i).getArrayChildren().get(i1);
}
#Override
public long getGroupId(int i) {
return i;
}
#Override
public long getChildId(int i, int i1) {
return i1;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
//in this method you must set the text to see the parent/group on the list
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
if (view == null) {
view = inflater.inflate(R.layout.list_item_parent, viewGroup,false);
}
view.findViewById(R.id.button).setTag(i);
view.findViewById(R.id.button).setOnClickListener(this);
TextView textView = (TextView) view.findViewById(R.id.list_item_text_view);
//"i" is the position of the parent/group in the list
textView.setText(getGroup(i).toString());
//return the entire view
return view;
}
#Override
//in this method you must set the text to see the children on the list
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
if (view == null) {
view = inflater.inflate(R.layout.list_item_child, viewGroup,false);
}
TextView textView = (TextView) view.findViewById(R.id.list_item_text_child);
//"i" is the position of the parent/group in the list and
//"i1" is the position of the child
textView.setText(mParent.get(i).getArrayChildren().get(i1));
//return the entire view
return view;
}
#Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
/* used to make the notifyDataSetChanged() method work */
super.registerDataSetObserver(observer);
}
/* (non-Javadoc)
* #see android.view.View.OnClickListener#onClick(android.view.View)
* #since Mar 20, 2013
* #author rajeshcp
*/
#Override
public void onClick(View v) {
if(mExpandableList.isGroupExpanded((Integer)v.getTag()))
{
mExpandableList.collapseGroup((Integer)v.getTag());
}else
{
mExpandableList.expandGroup((Integer)v.getTag());
}
}
}
}
Change your MyActivity like this and let me know what else you want ?
subject:
int width = getResources().getDisplayMetrics().widthPixels;
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
listView.setIndicatorBounds(width - getPixelValue(40), width - getPixelValue(10));
} else {
listView.setIndicatorBoundsRelative(width - getPixelValue(40), width - getPixelValue(10));
}
and helper method:
public static int getPixelValue(int dp) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
Just Create a view/Imageview where ever u want in the xml of group item example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parent_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="#+id/expandable_icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="6dp"
android:src="#drawable/group_icon_not_expanded" />
<TextView
android:id="#+id/group_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:fontFamily="#font/roboto_thin"
android:textColor="#android:color/black"
android:textSize="17sp" />
And then for your ExpandableListView use a GroupClickListener to change the image for ImageView programmatically, example :
listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
parent.smoothScrollToPosition(groupPosition);
if (parent.isGroupExpanded(groupPosition)) {
ImageView imageView = v.findViewById(R.id.expandable_icon);
imageView.setImageDrawable(getResources().getDrawable(R.drawable.group_icon_not_expanded));
} else {
ImageView imageView = v.findViewById(R.id.expandable_icon);
imageView.setImageDrawable(getResources().getDrawable(R.drawable.group_icon_expanded));
}
return false ;
}
});
I am a bit late to the party but my requirement was something similar to this but something was different.
I had 3 requirements:
if a group have child then show down_arrow (V)
if a group doesn't have a child then no arrow/image
if a group with child expanded then show up_arrow (^)
To achieve something similar to this:
Your ExpandableListView will look something similar to this with android:groupIndicator null
<ExpandableListView
android:id="#+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#android:color/darker_gray"
android:dividerHeight="0.5dp"
android:groupIndicator="#null" />
Your group/header layout will look something like this with text and image at the end:
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivDrawerHeaderItemIcon"
android:layout_width="#dimen/dp_30"
android:layout_height="#dimen/dp_30"
android:layout_gravity="center_vertical"
android:layout_marginStart="#dimen/dp_10"
android:layout_marginEnd="#dimen/dp_10"
android:src="#drawable/switch" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/lblListHeader"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="#dimen/dp_5"
android:layout_weight="1"
android:fontFamily="#font/roboto_condensed_regular"
android:gravity="center_vertical"
android:padding="#dimen/dp_10"
android:textAllCaps="true"
android:textColor="#android:color/white"
android:textSize="#dimen/sp_16" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivIcon"
android:layout_width="#dimen/dp_15"
android:layout_height="#dimen/dp_15"
android:layout_gravity="center_vertical"
android:layout_marginStart="#dimen/dp_10"
android:layout_marginEnd="#dimen/dp_10" />
In your BaseExpandableListAdapter's getGroupView() method, use
if (Objects.requireNonNull(expandableListDetail.get(expandableListTitle.get(listPosition))).size() > 0) {
if (isExpanded) {
ivIcon.setImageResource(R.drawable.arrow_up);
} else {
ivIcon.setImageResource(R.drawable.arrow_down);
}
}
Where, expandableListTitle is group and expandableListDetail is its children

Categories

Resources