How to change background of ExpandableListView's items - android

I have an ExpandableListView.
When a child is expanded it should be considered "selected". When a child is selected both the child and the child's children should display a different background (to show the user which is the current selected item).
Right now this is what I have:
XML
<ExpandableListView
android:id="#+id/listViewAccepted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:listSelector="#drawable/custom_selector" >
</ExpandableListView>
The ListView
setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View view,int groupPosition, long id) {
view.setSelected(true);
parent.setItemChecked(groupPosition, true);
return false;
}
});
The Selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#color/holo_blue_light" />
</shape>
</item>
<item android:state_selected="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item android:state_checked="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item android:state_focused="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item android:state_activated="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item>
<shape>
<solid android:color="#color/transparent" />
</shape>
</item>
</selector>

Here's how i did it, the following changes the group view. The overridden method is contained in my custom ExpandableListAdapter.
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View view, ViewGroup parent)
{
LinearLayout bevGroup = (LinearLayout) view.findViewById(R.id.myid);
if(isExpanded)
{
bevGroup.setBackgroundColor(context.getResources().getColor(R.color.bgGroupBlack));
}
else
{
bevGroup.setBackgroundColor(context.getResources().getColor(R.color.bgTransparent));
}
}
And the child, only ever being visible when expanded, is always the color it's supposed to be.

Related

Setting background of a list item

When I click on an item of a listView, the background of an other item than I have clicked is changed. If I click on the first one, the background of that and of the last item of the ListView is changing. If I scroll down and click on an item, the item after the one I clicked changes its color. What can I do to just change the selected item's background?
XML:
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/lvPlace"/>
Java:
lvPlace=(ListView) findViewById(R.id.lvPlace);
lvPlace.setAdapter(placeAdapter);
lvPlace.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
lvPlace.getChildAt(position).setBackgroundColor(myColors[0]);
}
});
You can set the background of the list item when you click with xml also
First add android:listSelector to listview
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:divider="#android:color/transparent"
android:dividerHeight="4.0sp"
android:listSelector="#drawable/list_row_selector"/>
Now create list_row_selector.xml in drawables
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/list_row_bg" android:state_pressed="false" android:state_selected="false"/>
<item android:drawable="#drawable/list_row_bg_hover" android:state_pressed="true"/>
<item android:drawable="#drawable/list_row_bg_hover" android:state_pressed="false" android:state_selected="true"/>
list_row_bg.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<padding android:left="10dp" android:right="10dp" android:top="10dp" android:bottom="10dp"/>
<gradient
android:startColor="#ffffff"
android:centerColor="#ffffff"
android:endColor="#ffffff"
android:angle="270" />
list_row_bg_hover.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<padding android:left="10dp" android:right="10dp" android:top="10dp" android:bottom="10dp"/>
<gradient
android:startColor="#18d7e5"
android:centerColor="#16cedb"
android:endColor="#09adb9"
android:angle="270" />
Hope this will work for you..!!
You can track the positions of your item.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
for (int j = 0; j < adapterView.getChildCount(); j++)
adapterView.getChildAt(j).setBackgroundColor(Color.TRANSPARENT);
// Change the background color of the selected element
//to your desire color
view.setBackgroundColor(Color.BLUE);
});

Scrollbar touch area in Android 6

I observe new behaviour in Android 6.0 Marshmallow. The touching area of scrollbar is widther than the scrollbar. It is visible on following screenshot. Scrollbar has 20 dp (green area) and touching area is probably 48 dp (blue and green area). I would like to have the touch area above the scrollbar only:
I use following:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="MyTheme.Dark" parent="android:Theme.Black">
<item name="android:fastScrollStyle">#style/Widget.FastScroll</item>
<item name="android:scrollbarThumbVertical">#drawable/dark_scrollbar_thumb</item>
<item name="android:scrollbarTrackVertical">#drawable/dark_scrollbar_track</item>
<item name="android:scrollbarSize">4dp</item>
<item name="android:fastScrollThumbDrawable">#drawable/dark_scrollbar_fast_thumb</item>
<item name="android:fastScrollTrackDrawable">#drawable/dark_scrollbar_fast_track</item>
</style>
<style name="Widget.FastScroll" parent="android:Widget.Material.FastScroll">
</style>
</resources>
dark_scrollbar_fast_thumb.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<size
android:height="30dp"
android:width="20dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
<item android:left="8dp" android:right="8dp">
<shape>
<size
android:height="30dp"
android:width="4dp" />
<solid android:color="#color/dark_secondary" />
</shape>
</item>
</layer-list>
dark_scrollbar_fast_track.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<size android:width="#dimen/1dp" />
<solid android:color="#color/dark_scrollbar_track" />
</shape>
dark_scrollbar_fast_thumb.xml:
<item>
<shape>
<size
android:height="30dp"
android:width="20dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
<item android:left="8dp" android:right="8dp">
<shape>
<size
android:height="30dp"
android:width="4dp" />
<solid android:color="#color/dark_secondary" />
</shape>
</item>
dark_scrollbar_fast_track.xml:
<size android:width="#dimen/1dp" />
<solid android:color="#color/dark_scrollbar_track" />
Fast scrollbar is always visible and I use following style in listviews:
<item name="android:scrollbarStyle">outsideInset</item>
But the result looks more like outsideOverlay. I can observe this issue only on Marshmallow devices.
I would like to find the attribute that causes it and change it from 48dp to 20dp. Would you please help me?
I encountered the same issue and ended up using a workaround.
The trick is to disable the fast scroll when the user is not scrolling (or 1 sec after he stopped scrolling), and reactivate it when he starts scrolling again.
In order to do so, youn need to implement OnScrollListener like this and set the listener to the listview:
private int mCurrentState = 0;
#Override
public void onScrollStateChanged(AbsListView absListView, int state) {
if (state == SCROLL_STATE_IDLE && mCurrentState != state && mListview.isFastScrollEnabled()){
mListview.postDelayed(new Runnable() {
#Override
public void run() {
mListview.setFastScrollEnabled(false);
}
},1000);
}
mCurrentState = state;
}
#Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
if (mCurrentState == SCROLL_STATE_TOUCH_SCROLL) {
if (!mListview.isFastScrollEnabled())
mListview.setFastScrollEnabled(true);
}
}
Hope this might help you
Found a simple solution which honestly I don't understand completely ;)
I created a view overlay for the blue section which should be touch insensitive for the fastscrollbar (parent view is a RelativeLayout).
<View
android:id="#+id/scroll_overlay
android:layout_width="25dp"
android:layout_marginRight="25dp"
android:alignParentTop="true"
android:alignParentRight="true"
android:layout_above="#id/my_list_view_bottom_bar"
android:clickable="true"/>
Then in my list view fragment, I set up an OnTouchListener for the overlay view to catch the touch events. The idea was to catch the MotionEvent.ACTION_DOWN to avoid jumping to the fast scrollbar position. But following code does that already.
View scrollOverlay = (View)view.findViewById(R.id.scroll_overlay);
scrollOverlay.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return myListView.onTouchEvent(event);
}
});

Android: Add divider between items in RecyclerView

I am using RecyclerView with rounded corner, to make it rounded corner I used below XML:
view_rounded.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#008f8471"/>
<stroke android:width="2dp" android:color="#ffffff" />
<corners android:radius="10dp"/>
</shape>
fragment_main.xml:-
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/view_rounded"/>
adapter_main.xml:-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/textTitle"
style="#style/AppTheme.ListTextView"
/>
</LinearLayout>
style.xml:-
<style name="AppTheme.ListTextView" parent="android:Widget.Material.TextView">
<item name="android:gravity">left</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textAllCaps">false</item>
<item name="android:padding">10dp</item>
<item name="android:textAppearance">#android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="android:textColor">#color/tabsScrollColor</item>
<item name="android:textStyle">bold</item>
</style>
Getting (without item separator):
Required (with item separator):
you should try add Divider
mListview.addItemDecoration(new DividerItemDecoration(this.getActivity(), LinearLayout.VERTICAL));
I have done this way:
onCreateView() of Fragment:
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));
SimpleDividerItemDecoration.java:
public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public SimpleDividerItemDecoration(Context context) {
mDivider = context.getResources().getDrawable(R.drawable.recycler_horizontal_divider);
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
recycler_horizontal_divider.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="#2EC590" />
</shape>
Hope this will help you.
RecyclerView works different from ListViews. You need to add ItemDecorators for the recycler view. As the docs says,
An ItemDecoration allows the application to add a special drawing and layout offset to specific item views from the adapter's data set. This can be useful for drawing dividers between items, highlights, visual grouping boundaries and more.
Take a look into this link : https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemDecoration.html
Well what I did to achieve this is, I first created layout for my adapter row as
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="#+id/lineView"
android:layout_width="match_parent"
android:layout_height="2px"
android:background="#android:color/black"/>
<TextView
android:id="#+id/textTitle"
style="#style/AppTheme.ListTextView"
/>
</LinearLayout>
Then in my adapter I checked for first row and changed its viewLine Visibility to invisible
#Override
public void onBindViewHolder(ChildInfoViewHolder holder, final int position) {
if(position == 0){
holder.viewLine.setVisibility(View.INVISIBLE);
}
//...
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
protected View viewLine;
public ChildInfoViewHolder(View view) {
super(view);
viewLine = view.findViewById(R.id.viewLine);
//...
}
}
To add dividers to your recyclerview you need to use decorator - https://gist.github.com/alexfu/0f464fc3742f134ccd1e after you add that to your project add a line
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
This line of code worked for me:
recyclerView.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.HORIZONTAL));
For vertical line, pass second argument as DividerItemDecoration.VERTICAL.
Set the selector at the background of the list item in your layout if you are using custom adapter
Try this one:
A very nice solution by Michel-F. Portzert
public class ClippedListView extends ListView {
public ClippedListView(Context context) {
super(context);
}
public ClippedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void dispatchDraw(Canvas canvas) {
float radius = 10.0f;
Path clipPath = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.dispatchDraw(canvas);
}
}
Try This From
Reference
Android: ListView with rounded corners
First off, we need the drawables for the backgrounds of the Lists entries:
For the entries in the middle of the list, we don't need rounded corners, so create a xml in your drawable folder "list_entry_middle.xml" with following content:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke android:width="1px" android:color="#ffbbbbbb" />
</shape>
</item>
<item android:bottom="1dp" android:left="1dp" android:right="1dp">
<shape >
<solid android:color="#ffffffff" />
</shape>
</item>
</layer-list>
For the rounded corners, create another xml, "rounded_corner_top.xml":
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke android:width="1dp" android:color="#ffbbbbbb" />
<corners android:topLeftRadius="20dp"
android:topRightRadius="20dp"
/>
</shape>
</item>
<item android:top="1dp" android:left="1dp" android:right="1dp" android:bottom="1dp">
<shape >
<solid android:color="#ffffffff" />
<corners android:topLeftRadius="20dp"
android:topRightRadius="20dp"
/>
</shape>
</item>
</layer-list>
Implementing the bottom part is quite the same, just with bottomLeftRadius and bottomRightRadius. (maybe also create one with all corners rounded, if the list only has one entry)
For better usability, also provide drawables with other colors for the different states, that the list item can have and reference them in another xml in the drawable folder ("selector_rounded_corner_top.xml") as followed:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/rounded_corner_top_click"
android:state_pressed="true" />
<item android:drawable="#drawable/rounded_corner_top_click"
android:state_focused="true" />
<item android:drawable="#drawable/rounded_corner_top" />
</selector>
Now do the same for the other backgrounds of the list.
All that is left now, is to assign the right backgrounds in our ListAdapter like following:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//...
//skipping the view reuse stuff
if (position == 0 && entry_list.size() == 1) {
view.setBackgroundResource(R.drawable.selector_rounded_corner);
} else if (position == 0) {
view.setBackgroundResource(R.drawable.selector_rounded_corner_top);
} else if (position == entry_list.size() - 1) {
view.setBackgroundResource(R.drawable.selector_rounded_corner_bottom);
} else {
view.setBackgroundResource(R.drawable.selector_middle);
}
//...
//skipping the filling of the view
}
Modify your ListView like below.Add the list_bg as the background of your ListView Also specify some padding for the top and the bottom of the listView otherwise the 1st and the last item in the list will overlap with the rounded corners showing rectangular corners.
<ListView
android:id="#+id/listView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#drawable/list_bg"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:fastScrollEnabled="true"
android:choiceMode="singleChoice" />
Use this drawable xml for curve shape listview and set background to your list view or any layout:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="6dp" />
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
</shape>
Try this
custom_rounded_list.xml :
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#ff2521"
android:endColor="#2f5511"
android:angle="270"/>
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners
android:bottomRightRadius="7dp"
android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>
Your listview:
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mylst"
android:background="#drawable/custom_rounded_list" />
you are setting list_selector for both textview and listview background. Use list_selector only for listview and if you want hover effect on textview too, then create another list_selector_textview which haven't include the <corners android:radius="10dp" property.
The problem is because you are setting the background with corners not only to the list view, but also to the item. You should make separate backgrounds for item (with selector) and one for list view with corners.
list_bg.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#008f8471"/>
<stroke android:width="1dip" android:color="#ffffff" />
<corners android:radius="10dp"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>
Now you can setup this drawable as the background of your list view.
<ListView
android:id="#+id/listView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#drawable/list_bg.xml"
android:fastScrollEnabled="true"
android:choiceMode="singleChoice" />
And for list view item you can use selector to have hover functionality:
list_item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/list_item_selected" android:state_pressed="true"/>
<item android:drawable="#drawable/list_item_selected" android:state_pressed="false" android:state_selected="true"/>
<item android:drawable="#android:color/transparent"/>
Where list_item_selected is :
list_item_selected.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4d8f8471"/>
<stroke android:width="1dip" android:color="#ffffff" />
</shape>
And after that you can setup this selector to the item in your xml:
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_item_selector" />
So your list view will have always same background with corners, and the background of items of list view, will be without corners and will be changed in pressed or selected state.
Just One Line...
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null));
That's all
Try this
recyclerView.apply {
....
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
}

Circle button with shadow

I make a circle button with states and I want to add shadow to the button like the default buttons how I can do this? Here is my code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#color/yellow_pressed" />
<stroke android:width="1dp" android:color="#fff" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="oval">
<solid android:color="#color/yellow_pressed" />
<stroke android:width="1dp" android:color="#fff" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="#color/yellow_default" />
<stroke android:width="1dp" android:color="#fff" />
</shape>
</item>
</selector>
Starting from Lollipop, you can use:
public static void setOvalElevationToView(final View view) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
view.setOutlineProvider(new ViewOutlineProvider() {
#TargetApi(VERSION_CODES.LOLLIPOP)
#Override
public void getOutline(View view, Outline outline) {
final int size = view.getWidth();
outline.setOval(0, 0, size, size);
}
});
}
You might also need to disable clipping on the parent of the view, so that the shadows won't be clipped

How to modify click style of ListView

I use below code to modify style of ListView item click.
list_four_corner_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#drawable/list_four_corner_selected"
/>
<item
android:drawable="#drawable/list_four_corner_unselect"
/>
</selector>
list_four_corner_unselect.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#FFFFFF"
android:endColor="#FFFFFF"
android:angle="270"/>
<corners android:bottomLeftRadius="10dip"
android:bottomRightRadius="10dip"
android:topRightRadius="10dip"
android:topLeftRadius="10dip" />
<stroke
android:width="1dp"
android:color="#dddddd"
android:dashWidth="10dp"
android:dashGap="0dp" />
</shape>
list_four_corner_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#B7D5F9"
android:endColor="#B7D5F9"
android:angle="270"/>
<corners android:bottomLeftRadius="10dip"
android:bottomRightRadius="10dip"
android:topLeftRadius="10dip"
android:topRightRadius="10dip" />
</shape>
And below code in BaseAdapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewTag viewTag;
if(convertView == null) {
convertView = myInflater.inflate(R.layout.row_item, null);
viewTag = new ViewTag((TextView)convertView.findViewById(R.id.row_title));
convertView.setTag(viewTag);
}
else {
viewTag = (ViewTag)convertView.getTag();
}
convertView.setBackgroundResource(R.drawable.list_four_corner_selector);
}
But while I click item, the item's four corner will display the default color.
I want to let the default hide.
How can I do it?
Try using android:listSelector on the ListView.

Categories

Resources