Frame layout foreground property is not working in grid view - android

iam developing an android custom gallery where am using grid view and a framelayout as gridview item(for foreground property for selector). everthing works fine , but it's not drawing it's selected state after scrolling ..
here is my get view method
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final GalleryHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.gridview_child_gallery_item, parent, false);
holder = new GalleryHolder();
holder.folderThumbnail = (RecyclingImageView) convertView.findViewById(R.id.iv_thumbnail);
holder.baseLayout = (GalleryFrameLayout) convertView.findViewById(R.id.baseItemLayout);
convertView.setTag(holder);
} else
holder = (GalleryHolder) convertView.getTag();
if(mSelections.contains(String.valueOf(position))){
holder.baseLayout.setSelected(true);
}
else{
holder.baseLayout.setSelected(false)
}
if(getGallerytype().equals(GallerySwitcherFragment.IMAGES))
loadBitmap(GallerySwitcherFragment.IMAGES,
Long.valueOf(mFiles.get(position).getThumbnailData()), holder.folderThumbnail);
else
loadBitmap(GallerySwitcherFragment.VIDEOS,
Long.valueOf(mFiles.get(position).getThumbnailData()),holder.folderThumbnail);
holder.baseLayout.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
setMultiSelectionEnabled(true);
holder.baseLayout.setChecked(true);
mController.toggleActionBarItems(true);
return true;
}
});
holder.baseLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(isMultiSelectionEnabled){
if(mSelections.contains(String.valueOf(position)))
mSelections.remove(String.valueOf(position));
else
mSelections.add(String.valueOf(position));
}
else
return;
}
});
return convertView;
}
and here is my xml
<?xml version="1.0" encoding="utf-8"?>
<com.sams.customcomponents.GalleryFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="119dp"
android:descendantFocusability="blocksDescendants"
android:id="#+id/baseItemLayout"
android:addStatesFromChildren="true"
android:foreground="#drawable/gridview_selector" >
<com.sams.customcomponents.RecyclingImageView android:id="#+id/iv_thumbnail"
android:contentDescription="#string/iv_content_description"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="#color/transparent_black" />
</com.sams.customcomponents.GalleryFrameLayout>
here is my selector
<?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/selector_blue"/> <!-- pressed state -->
<item android:state_focused="true"
android:drawable="#color/selector_blue"/> <!-- focused state -->
<item android:state_selected="true"
android:drawable="#color/selector_blue"/> <!-- selected state -->
<item android:drawable="#android:color/transparent"/> <!-- default state -->
</selector>

Related

Remove Android Spinner onClick item background [duplicate]

This question already has answers here:
How to customize a Spinner in Android
(6 answers)
Closed 5 years ago.
I'm trying to remove the default highlight effect for Spinner item's onClick. I have my own specific spinner background which have radius in its corners. When I applied the new background, it still has its default background under my custom background. I've tried styling like this:
<style name="ExternalPSpinnerTheme" parent="Widget.AppCompat.Spinner.DropDown">
<item name="android:listSelector">#color/transparent</item>
<item name="android:listChoiceBackgroundIndicator">#color/transparent</item>
<item name="android:listChoiceIndicatorSingle">#color/transparent</item>
<item name="android:selectableItemBackground">#color/transparent</item>
<item name="android:background">#drawable/spinner_sortfriend_background</item>
<item name="android:cacheColorHint">#android:color/transparent</item>
<item name="android:popupBackground">#drawable/spinner_sortfriend_background</item>
<item name="android:dropDownSelector">#color/transparent</item>
</style>
I've tried changing the parent to Widget.AppCompat.Spinner but it didn't work.. PopupBackground and background works tho.
The other question is questioning on how to hide dividers and add its own spinner custom implementation, mine is asking about how to remove the default onClick highlight effect on the background. How did I try to achieve it? This is how:
if (position > 0 &&
(position + 1) < mDataset.size()){
divider.setVisibility(View.VISIBLE);
convertView.setBackground(ContextCompat.getDrawable(context, R.drawable.spinner_dropdown_background_middle_white_to_migrey));
} else if (position == 0){
divider.setVisibility(View.VISIBLE);
convertView.setBackground(ContextCompat.getDrawable(context, R.drawable.spinner_dropdown_background_top_white_to_migrey));
} else if (position + 1 == mDataset.size()){
divider.setVisibility(View.GONE);
convertView.setBackground(ContextCompat.getDrawable(context, R.drawable.spinner_dropdown_background_bottom_white_to_migrey));
}
And I still didn't get the right answer, I even tried the solution in the other question. I just realized something tho, only the background on the first item overlaps with my custom background click effect, but the one at the end of the list doesn't get overlapped.. Weird..
Any solution?
Create custom Spinner Layout in your xml as follows
<RelativeLayout
android:id="#+id/relativeLayout_multiChoiceDropDown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/drawable_border_profile">
<TextView
android:id="#+id/textView_multiChoiceDropDownText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginBottom="#dimen/margin_5dp"
android:layout_marginEnd="#dimen/margin_5dp"
android:layout_marginStart="#dimen/margin_5dp"
android:layout_marginTop="#dimen/margin_5dp"
android:layout_toStartOf="#+id/button_multiChoiceDropDownArrow"
android:padding="#dimen/margin_5dp"
android:text="Select Item"
android:textColor="#color/black"
android:textSize="#dimen/text_size_16"/>
<Button
android:id="#+id/button_multiChoiceDropDownArrow"
android:layout_width="#dimen/profile_multi_choice_width"
android:layout_height="#dimen/profile_multi_choice_height"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_margin="#dimen/margin_5dp"
android:background="#drawable/dropdownarrow"/>
</RelativeLayout>
drawable_border_profile.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#80FFFFFF"/>
<stroke
android:width="0.5dp"
android:color="#color/light_gray"/>
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp"/>
</shape>
Then Set OnClickListener on RelativeLayout. On that You can open Popup Window
LayoutInflater inflater = (LayoutInflater)parentActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.pop_up_window, null);
RelativeLayout layout1 = holder.relativeLayout_multiChoiceDropDown;
pw = new PopupWindow(layout, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchable(true);
pw.setOutsideTouchable(true);
pw.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
pw.setTouchInterceptor(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_OUTSIDE)
{
pw.dismiss();
return true;
}
return false;
}
});
pw.setContentView(layout);
pw.showAsDropDown(layout1, -5, 0);
final ListView list = (ListView) layout.findViewById(R.id.dropDownList);
Adapter_DropDown adapter = new Adapter_DropDown(parentActivity, items);
list.setAdapter(adapter);
pop_up_window.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="#+id/PopUpView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/qatool_basic_info_dropdown"
android:orientation="vertical">
<ListView
android:id="#+id/dropDownList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#000"
android:dividerHeight="0.5dp">
</ListView>
You can use customArray Adapter
public class Adapter_Spinner extends ArrayAdapter
{
Context context;
List<Response_IdDesc> dataArray;
public Adapter_Spinner(Context context, int textViewResourceId, List<Response_IdDesc> dataArray)
{
super(context, textViewResourceId, dataArray);
this.dataArray = dataArray;
this.context = context;
}
#Override public Response_IdDesc getItem(int position)
{
return dataArray.get(position);
}
#Override public int getCount()
{
return dataArray.size();
}
#Override public int getPosition(Object item)
{
return dataArray.indexOf(item);
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent)
{
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.rowitem_spinner_profile, parent, false);
TextView label = (TextView) view.findViewById(R.id.textview_spinner);
label.setText(dataArray.get(position).DESC);
return view;
}
}
Then set your spinner adapter like this
Adapter_Spinner adapter_spinner = new Adapter_Spinner(parentActivity, R.layout.rowitem_spinner, list);
spinner.setAdapter(adapter_spinner);

Android - Listview/Gridview item selection with scrolling

I am new to android and I have just started programming a simple app to try different things out.
I was programming a ListView (and, in the same way a GridView) but there is something I got wrong. Each item is a couple of an image and a text field.
| img | __text__ |
I want to be able to choose any number of list items, keeping them enlightened for all the selection process, before passing the selected items to the next activity. If I want to
de-select one of them, I simply have to re-click on the item to have the selection disappear. For this purpose I use a custom selector so that when the item is pressed it changes colours.
If the items are all contained in a screen, everything is ok. But as soon as they grow in number and recycling kicks in, the enlightening of selected items which get out of the screen is lost. I have debugged the state of items and those whose enlightening is lost are still correctly selected, so I think it’s just a problem on how the graphic reloads when an item is restored after it went out of the device screen.
Here’s the code of the activity layout:
<!-- items_selection.xml -->
<?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="match_parent"
android:orientation="vertical"
android:background="#color/Background">
<ListView
android:id="#+id/item_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#color/divider"
android:dividerHeight="3dp"
android:choiceMode="multipleChoice"
android:listSelector="#drawable/list_selector">
</ListView>
</LinearLayout>
This is the Row Item layout:
<!-- list_row.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >
<LinearLayout
android:id="#+id/item_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dip"
android:padding="3dip" >
<ImageView
android:id="#+id/item_image"
android:layout_width="#dimen/img_side"
android:layout_height="#dimen/img_side" />
</LinearLayout>
<TextView
android:id="#+id/item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/item_list_item"
android:layout_centerVertical="true"
android:textColor="#color/black"
android:textSize="#dimen/textnorm"
/>
</RelativeLayout>
This is the selector I used:
<!-- list_selector.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/rect" />
<item
android:state_pressed="true"
android:drawable="#drawable/rect_sel" />
<item
android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/rect_sel" />
</selector>
<!-- rect.xml -->
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#D5DDE0"
android:centerColor="#e7e7e8"
android:endColor="#CFCFCF"
android:angle="270" />
</shape>
<!-- rect_sel.xml -->
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#78DDFF"
android:centerColor="#16cedb"
android:endColor="#09adb9"
android:angle="270" />
</shape>
This is the code of the Activity:
public class ItemSelection extends AppCompatActivity {
private int numitems;
private ListView listview;
private ArrayList<Item> items = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.items_selection);
numitems = 15;
build_list();
listview = (ListView) findViewById(R.id.item_list);
listview.setAdapter(new ListAdapter(this, items));
}
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.next_btn, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id){
case R.id.next_btn:
Intent intent = new Intent (this, nextActivity.class);
intent.putStringArrayListExtra("items", Chosen_Items());
startActivity(intent);
return true;
default:
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
}
}
private void build_list() {
//Populates the item list with more items than the screen can support.
}
private ArrayList<String> Chosen_Items(){
ArrayList<String> selitems = new ArrayList<>();
for (int i=0; i<numitems; i++){
if (items.get(i).isSelected()){
selitems.add(items.get(i).getName());
}
}
return selitems;
}
This is the code of the listAdapter:
public class ListAdapter extends BaseAdapter {
private ArrayList <Item> items;
private Activity sActivity;
public ListAdapter(Activity sActivity, ArrayList<Item> items) {
this.sActivity = sActivity;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder holder;
if(view == null) {
LayoutInflater li = sActivity.getLayoutInflater();
view = li.inflate(R.layout.list_row, null);
holder = new ViewHolder();
holder.text = (TextView)view.findViewById(R.id.item_name);
holder.img = (ImageView)view.findViewById(R.id.item_image);
view.setTag(holder);
}
else {
holder = (ViewHolder)view.getTag();
}
holder.text.setText(items.get(position).getName());
holder.img.setImageResource(items.get(position).getImage());
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View viewitem) {
if (!viewitem.isSelected() && !items.get(position).isSelected()) {
viewitem.setSelected(true);
items.get(position).setSelected(true);
}
else {
viewitem.setSelected(false);
items.get(position).setSelected(false);
}
}
});
return view;
}
private static class ViewHolder{
public TextView text;
public ImageView img;
}
}
I have already tried to manually set the background color of the items re-entering the screen (by using
view.setBackgroundResource(R.drawable.rect_sel)
in the adapter, before the click handler) but the problem remains. Can anyone help me solving the problem?
~~~~~~~~~~~~~~~~~~~ SOLUTION ~~~~~~~~~~~~~~~~~~
It seems the selector doesn't follow the recycle of the items and their views.There has to be a better and more elegant solution taking advantage of a selector in this situation. But out of all the attempts i made, none has worked. This solution is the best workaround and does not use the selector.
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder holder;
if(view == null) {
LayoutInflater li = sActivity.getLayoutInflater();
view = li.inflate(R.layout.list_row, null);
holder = new ViewHolder();
holder.text = (TextView)view.findViewById(R.id.item_name);
holder.img = (ImageView)view.findViewById(R.id.item_image);
view.setTag(holder);
}
else {
holder = (ViewHolder)view.getTag();
}
holder.text.setText(items.get(position).getName());
holder.img.setImageResource(items.get(position).getImage());
if(items.get(position).isSelected()){
view.setBackgroundResource(R.drawable.rect_sel);
}else{
view.setBackgroundResource(R.drawable.rect);
}
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View viewitem) {
if (!viewitem.isSelected() && !items.get(position).isSelected()) {
viewitem.setBackgroundResource(R.drawable.rect_sel);
viewitem.setSelected(true);
items.get(position).setSelected(true);
}
else {
viewitem.setBackgroundResource(R.drawable.rect);
viewitem.setSelected(false);
items.get(position).setSelected(false);
}
}
});
return view;
}
private static class ViewHolder{
public TextView text;
public ImageView img;
}
While in the list_row.xml file, the following line can be just deleted:
android:background="#drawable/list_selector"
In your getView() method just add this test:
if (items.get(position).isSelected()){
view.setBackgroundResource(R.drawable.rect_sel);
} else {
view.setBackgroundResource(R.drawable.rect);
}
Or just view.setSelected(items.get(position).isSelected());. While you already have a selector for your list item.
You must define the current selection state of view inside getView method.
Add this line:
viewitem.setSelected(items.get(position).isSelected());
after viewholder has been created like:
holder.img.setImageResource(items.get(position).getImage());
viewitem.setSelected(items.get(position).isSelected());
I think you should set the id for your RelativeLayout then add it to ViewHolder
private static class ViewHolder{
public TextView text;
public ImageView img;
RelativeLayout rl;
}
After that you handle event when click RelativeLayout then change background for RelativeLayout
public View getView(...)
...
...
// you should update the state of relative layout first
if (items.get(position).isSelected()) {
holder.setBackgroundColor(Color.parseColor("#ffff00"));
}else{
holder.setBackgroundColor(Color.parseColor("#ff0000"));
}
holder.rl.setOnClickListener(new View.OnClickListener(){ //remmember it is rl.setOnClick... not view.setOnClick...
public void onClick(View v) {
if (!items.get(position).isSelected()) {
items.get(position).setSelected(true);
holder.setBackgroundColor(Color.parseColor("#ffff00"));
}else {
items.get(position).setSelected(false);
holder.setBackgroundColor(Color.parseColor("#ff0000"));
}
}
});
}
Suggestion
You should modify your row layout like this (I have removed LinearLayout but the new layout still good)
<!-- list_row.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >
<ImageView
android:id="#+id/item_image"
android:layout_marginRight="5dip"
android:padding="3dip"
android:layout_alignParentLeft="true"
android:layout_width="#dimen/img_side"
android:layout_height="#dimen/img_side" />
<TextView
android:id="#+id/item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/item_image"
android:layout_centerVertical="true"
android:textColor="#color/black"
android:textSize="#dimen/textnorm"
/>
</RelativeLayout>
Remember that your list row layout is more simple then your listview will scroll faster, smooth and prevent some annoying bug.
Hope this help

Android Custom Listview Programmatically Click Item

I am using a custom single choice listview. I want to call ItemOnClickListener programmatically. I am using android:listSelector="#47D149" property in my xml. I saw this post. performItemClick function is working but doesn't change the background of list item.
What should I do?
Any suggestions. Thanks!
SAMPLE
ListView
<ListView
android:id="#+id/navigation_menu_container"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_below="#id/rlBanner"
android:layout_gravity="start"
android:background="#color/nyc_black"
android:choiceMode="singleChoice"
android:divider="#color/border_black"
android:dividerHeight="#dimen/divider_height"
android:listSelector="#drawable/item_selector" >
drawables/item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_activated="false" android:drawable="#drawable/item_normal"></item>
<item android:state_pressed="true" android:drawable="#drawable/item_pressed"></item>
<item android:state_activated="true" android:drawable="#drawable/item_pressed"></item>
</selector>
drawables/item_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid
android:color="#color/black"
/>
</shape>
drawables/item_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid
android:color="#color/red"
/>
</shape>
Try the above sample. :) tell me if it works
Ok. I have found the solution. :) #Shifar Shifz answer, dont use
android:listSelector="#drawable/item_selector"
Instead of it, add this drawable xml to your row.xml layout as background
android:background="#drawable/item_selector"
Maybe you could just take care of it in your adapter itself?
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (null == convertView) {
LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, parent, false);
}
if(this.getItem(position).isChecked()){
convertView.setBackgroundResource(android.R.color.holo_blue_bright);
}else{
convertView.setBackgroundResource(android.R.color.white);
}
final View tempFinalView = convertView;
tempFinalView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getItem(position).isChecked()) {
getItem(position).setChecked(false);
tempFinalView.setBackgroundResource(R.color.white);
} else {
getItem(position).setChecked(true);
tempFinalView.setBackgroundResource(R.color.pressed);
}
}
}
);
return convertView;
}
EDIT:
If you dont want to add another variable to the item.You could use the tag feature instead.
Just set and get the tag.
private static int VIEW_TAG=99;
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (null == convertView) {
LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, parent, false);
}
if((Boolean)convertView.getTag(VIEW_TAG)){
convertView.setBackgroundResource(android.R.color.holo_blue_bright);
}else{
convertView.setBackgroundResource(android.R.color.white);
}
final View tempFinalView = convertView;
tempFinalView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getItem(position).isChecked()) {
convertView.setTag(VIEW_TAG,new Boolean(false));
tempFinalView.setBackgroundResource(R.color.white);
} else {
convertView.setTag(VIEW_TAG,new Boolean(true));
tempFinalView.setBackgroundResource(R.color.pressed);
}
}
}
);
return convertView;
}

Color background cannot be set to single cell in GridView Android

I have weird problem with setting color of single cell in GridView.
Problem description :
My gridview constains a lot of single cells which contains simple text. I have set ViewHolder to maintain certain position for each cell. User can click on each item and then it should change its color to other. Changing color works, but it also changes color of cells which haven't been selected. This shows only when I scroll gridview up and down. Then background colors get mixed.
Here is my HintGridAdapter :
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.chips_hint_grid, parent, false);
viewHolder = new ViewHolder();
viewHolder.hintTag = (TextView) convertView.findViewById(R.id.hint_tag);
viewHolder.hintTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.hintTag.setBackgroundColor(context.getResources().getColor(R.color.color_accent));
chips.setText(chips.getText() + tags[position] + ", ");
chips.setChips();
}
});
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.hintTag.setText(tags[position]);
return convertView;
}
private static class ViewHolder {
TextView hintTag;
}
As you can see, I have set background color to specific hintTag.
And XMLs :
<?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="50dp"
android:orientation="vertical">
<TextView
android:id="#+id/hint_tag"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="8dp"
android:text="#string/tag"
android:background="#drawable/hint_button_selector"
android:textColor="#color/grey_white_1000"
android:textSize="12sp" />
</RelativeLayout>
and this is hint_button_selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/color_accent" android:state_activated="true" />
<item android:drawable="#color/color_accent" android:state_selected="true" />
<item android:drawable="#color/color_accent" android:state_pressed="true" />
<item android:drawable="#color/color_accent" android:state_checked="true" />
<item android:drawable="#color/black_opacity_55" />
</selector>
Color change should work in selector but it doesn't.
Declare a arrayList of Int type.
ArrayList<Integer> clickedPos=new ArrayList<>();
Then update your getView as
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.chips_hint_grid, parent, false);
viewHolder = new ViewHolder();
viewHolder.hintTag = (TextView) convertView.findViewById(R.id.hint_tag);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.hintTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!clickedPos.contains(position))
clickedPos.add(position);
viewHolder.hintTag.setBackgroundColor(context.getResources().getColor(R.color.color_accent));
chips.setText(chips.getText() + tags[position] + ", ");
chips.setChips();
}
});
if(clickedPos.contains(position))
viewHolder.hintTag.setBackgroundColor(context.getResources().getColor(R.color.color_accent));
else
viewHolder.hintTag.setBackgroundColor(context.getResources().getColor(R.color.default_color));
viewHolder.hintTag.setText(tags[position]);
return convertView;
}
You can add else condition to set background color default if clicked again.

Android GridView Selector Issue

I am using a StaggeredGridView in my application with a custom selector created by me but i must have gotten something terribly wrong with my selector because when i select an item in the gridview, all of the items change their color to green.
Here is the code for gridview item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/grid_item_selector">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ro.gebs.zonizbeacon.ui.custom.ScaledNetworkImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ro.gebs.zonizbeacon.ui.custom.AngledTextView
android:id="#+id/expired_tv"
android:layout_width="#dimen/size_favorite_angle_text"
android:layout_height="#dimen/size_favorite_angle_text"
app:angledText="#string/expired"
app:backgroundColor="#android:color/holo_orange_dark"
app:angledTextColor="#android:color/white"
app:angledTextSize="#dimen/font_size_plus" />
</RelativeLayout>
<ro.gebs.zonizbeacon.ui.custom.fonts.CustomFontTextView
android:id="#+id/store_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/default_padding"
android:textSize="#dimen/font_size_normal"
android:text="Zara"
app:fontName="Bold" />
<ro.gebs.zonizbeacon.ui.custom.fonts.CustomFontTextView
android:id="#+id/offer_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:fontName="Regular"
android:paddingLeft="#dimen/default_padding"
android:paddingRight="#dimen/default_padding"
android:paddingBottom="#dimen/default_padding"
android:textSize="#dimen/font_size_small"
android:text="#string/info_about" />
</LinearLayout>
This is my selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_pressed="true" android:drawable="#color/green_main_color" />
<item android:state_enabled="true" android:state_focused="true" android:drawable="#color/green_main_color" />
<item android:state_enabled="true" android:state_selected="true" android:drawable="#color/green_main_color" />
<item android:drawable="#android:color/white" />
</selector>
This is my adapter class:
public class FavoritesAdapter extends ArrayAdapter<Offer> {
LayoutInflater mLayoutInflater;
public FavoritesAdapter(Context context, List<Offer> objects) {
super(context, 0, objects);
mLayoutInflater = LayoutInflater.from(context);
}
/* #Override
public long getItemId(int position) {
return position;
}*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.item_favorite_offer, null);
holder = new ViewHolder();
holder.imageView = (ScaledNetworkImageView) convertView.findViewById(R.id.imageView1);
holder.offerText = (CustomFontTextView) convertView.findViewById(R.id.offer_text);
holder.storeName = (CustomFontTextView) convertView.findViewById(R.id.store_name);
holder.expiredTv = (AngledTextView) convertView.findViewById(R.id.expired_tv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//holder.offerText.setText("POSITION + "+position);
final Offer offer = getItem(position);
Date d = Calendar.getInstance().getTime();
if (offer.getActiveUntil() < d.getTime()) {
holder.expiredTv.setVisibility(View.VISIBLE);
} else {
holder.expiredTv.setVisibility(View.INVISIBLE);
}
ImageUtils.load(holder.imageView, offer.getPngLink(), R.drawable.image_placeholder, R.drawable.image_placeholder);
holder.offerText.setText(offer.getDescription());
holder.storeName.setText(offer.getStoreName());
return convertView;
}
static class ViewHolder {
AngledTextView expiredTv;
ScaledNetworkImageView imageView;
CustomFontTextView offerText;
CustomFontTextView storeName;
}
}
and in my fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_favorites, container, false);
gridView = (StaggeredGridView) view.findViewById(R.id.staggeredGridView1);
//gridView.setSelector(new ColorDrawable(getResources().getColor(R.color.green_main_color)));
gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));
emptyText = (CustomFontTextView) view.findViewById(R.id.empty_grid_view);
int margin = getResources().getDimensionPixelSize(R.dimen.default_padding);
int itemMargin = getResources().getDimensionPixelSize(R.dimen.padding_tell_button);
gridView.setItemMargin(itemMargin); // set the GridView margin
gridView.setPadding(margin, margin, margin, 0); // have the margin on the sides as well
mFavoritesAdapter = new FavoritesAdapter(getActivity(), new ArrayList<Offer>());
mFavoritesAdapter.setNotifyOnChange(false);
gridView.setAdapter(mFavoritesAdapter);
gridView.setOnItemClickListener(new StaggeredGridView.OnItemClickListener() {
#Override
public void onItemClick(StaggeredGridView parent, View view, int position, long id) {
Offer o = mFavoritesAdapter.getItem(position);
if (o != null) {
Intent intent = new Intent(getActivity(), WebViewActivity.class);
intent.putExtra(WebViewActivity.BUNDLE_HTML_LINK, o.getHtmlLink());
intent.putExtra(WebViewActivity.STORE_NAME, o.getStoreName());
startActivity(intent);
}
//getActivity().finish();
}
});
gridView.setOnItemLongClickListener(mOnItemLongClickListener);
//restartLoader(LOADER_FAVORITES);
return view;
}
Any ideas as to why it could be wrong?
Maybe your listitems get the state of focussed (while not intended). I always use a selector build like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_mediumAnimTime" >
<item android:state_selected="true" android:drawable="#color/green_bit_transparent"/>
<item android:state_pressed="false" android:state_focused="true" android:state_selected="false" android:drawable="#color/green_bit_transparent" />
<item android:state_pressed="true" android:state_selected="false" android:drawable="#color/green" />
<item android:drawable="#android:color/transparent" />
</selector>

Categories

Resources