I have an AdapterView filled with items
and I would like to select the item I click on, something like this:
is there a possible way I can do this?
This is how I build the adapter
adapter = new ArrayAdapter<String>(
context,
android.R.layout.simple_selectable_list_item,
QuestionActivity.OptionArrayList.get(position));
context.startActivity(i);
You can check this sample project I just made. I think the code speaks for itself but feel free to ask questions if You aren't sure about something. But basically I set OnItemClickListener to the ListView and I change the background to selected_back which is a shape in drawable folder. Also, I keep a reference to the last changed View so when user click on another View it will be easy to change its background again to normal_back.
MainActivity.java
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity
{
View lastChangedView = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("One");
arrayList.add("Two");
arrayList.add("Three");
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this,
R.layout.list_view_item,
arrayList);
ListView listView = findViewById(R.id.listView);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
if (lastChangedView != null)
{
lastChangedView.setBackgroundResource(R.drawable.normal_back);
}
lastChangedView = view;
Log.d("Main", "Item click at " + position);
view.setBackgroundResource(R.drawable.selected_back);
}
});
}
}
acitivty_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
list_view_item.xml (in layout folder)
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="32sp"
android:background="#drawable/normal_back" />
normal_back.xml (in a drawable folder)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
</shape>
selected_back.xml (in a drawable folder)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<stroke
android:width="2dp"
android:color="#0000FF" />
<solid android:color="#FFFFFF" />
</shape>
Result (after clicking on "Two"):
You need a custom adapter to achieve this. It will simply extend BaseAdater, and will have a custom view along with a boolean to keep info of which item was selected. You can follow Using a BaseAdapter with ListView guide.
CustomAdatpter class will be as follows -
public class MyAdapter extends BaseAdapter {
private Context context;
private ArrayList<String> arrayList;
//taking boolean to keep track of item selected
private boolean isItemSelected = false;
public MyAdapter(Context context, ArrayList<String> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public Object getItem(int position) {
return arrayList.get(position); //returns list item at the specified position
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).
inflate(R.layout.item, parent, false);
}
TextView textView = (TextView) convertView.findViewById(R.id.text_view);
textView.setText(arrayList.get(position));
//setting click listener on convertView which is each item view
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isItemSelected){
//item is selected, need to un select item,
isItemSelected = false;
textView.setBackgroundResource(R.drawable.unselected_bg);
}
else{
//item is not selected, need to select item
isItemSelected = true;
textView.setBackgroundResource(R.drawable.selected_bg);
}
}
});
return convertView;
}
}
I am using R.drawable.unselected_bg and R.drawable.selected_bg which are nothing but drawable files as follows -
selected_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#5B5BC9"/>
<stroke android:color="#4CAF50" android:width="5dp"/>
</shape>
unselected_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#5B5BC9"/>
</shape>
In last item has following layout which was inflated in getView();
item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:clickable="true"
android:focusable="true"
android:id="#+id/text_view"
android:background="#drawable/unselected_bg"
android:padding="16dp">
</TextView>
If you notice, I have given android:background="#drawable/unselected_bg" just to make item unselected on create.
Result will be as follows -
Happy Coding !
Related
I have a problem with the following exception:
exception:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
I have an Adapter class:
public class SimpleAdapter extends BaseAdapter {
private LayoutInflater lInflater;
private String [] simpleValueList;
public SimpleAdapter(Context context, String[] simpleValueList) {
lInflater = LayoutInflater.from(context);
this.simpleValueList = simpleValueList;
}
#Override
public int getCount() {
return simpleValueList.length;
}
#Override
public Object getItem(int position) {
return simpleValueList[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.test, parent, false);
TextView textSimple = view.findViewById(R.id.simple_list);
textHours.setText(simpleValueList[position]);
}
return view;
}
}
my CustomView class:
public class SimpleView extends View {
private String[] valueList = {"aa", "2", "bb", "3"};
private ListView listView;
private SimpleAdapter simpleAdapter;
public SimpleView(Context context, ViewGroup mviewGroup) {
super(context);
inflate(context, R.layout.test, mviewGroup);
listView = findViewById(R.id.simple_list);
simpleAdapter = new SimpleAdapter(context, valueList);
listView.setAdapter(simpleAdapter);
}
}
my Activity class:
public class SimpleActivity extends AppCompatActivity {
private SimpleView simpleView;
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout linearLayout = findViewById(R.id.custom_view);
simpleView = new SimpleView(this, linearLayout);
linearLayout.addView(simpleView);
}
}
test. xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="100dp"
android:layout_height="220dp"
android:layout_gravity="center">
<ListView
android:id="#+id/simple_list"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#color/orange" />
</LinearLayout>
my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/custom_view"
android:layout_width="400dp"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
If I do not add the Adapter in the SimpleView class then it works. But if I add the Adapter in the SimpleView class I get the exception:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference. (at ...here: listView.setAdapter(simpleAdapter); (simpleView = new SimpleView(this, linearLayout));
The problem is that the code is calling the SimpleView's version of findViewById which is using test.xml, but the ListView is located in activity_main.xml in the SimpleActivity.
listView = findViewById(R.id.custom_view1);
This will return null because there is no view with the ID R.id.custom_view1 inside SimpleView.
There probably is not any need for the SimpleView class. The following lines of code could be moved into onCreate in SimpleActivity:
listView = findViewById(R.id.custom_view1);
simpleAdapter = new SimpleAdapter(context, valueList);
listView.setAdapter(simpleAdapter);
If you do want to create a CustomView on the other hand, all the views you are working with need to be in R.layout.test. You could in theory, move the ListView in there, but I think it is probably unnecessary. I would just inflate, find it and set the adapter in onCreate of the Activity.
If you do want an abstraction to contain the ListView, I would investigate putting it into a Fragment.
EDIT:
If it has to be done with a custom view then make sure the following is in test.xml:
<ListView
android:id="#+id/custom_view1"
android:layout_width="71dp"
android:layout_height="77dp"
android:orientation="vertical">
It is important to use this ID android:id="#+id/custom_view1 so that it matches up with listView = findViewById(R.id.custom_view1); in the Java code.
To void the crash you are getting now:
public SimpleView(Context context, ViewGroup mviewGroup) {
super(context);
View layout = inflate(context, R.layout.test, mviewGroup);
listView = layout.findViewById(R.id.simple_list);
simpleAdapter = new SimpleAdapter(context, valueList);
listView.setAdapter(simpleAdapter);
}
Make sure you do the find on the value being returned from inflate.
=== Code Dump ===:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/custom_view_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
test.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ListView
android:id="#+id/simple_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="100dp"
android:layout_height="220dp"
android:layout_gravity="center">
<TextView
android:id="#+id/txt"
android:layout_width="100dp"
android:layout_height="100dp"/>
</LinearLayout>
ActivityMain.java:
package com.example.myapplication2000;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout linearLayout = findViewById(R.id.custom_view_container);
SimpleView simpleView = new SimpleView(this, linearLayout);
linearLayout.addView(simpleView);
}
}
SimpleView.java:
package com.example.myapplication2000;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class SimpleView extends View {
private String[] valueList = {"aa", "2", "bb", "3"};
private ListView listView;
private SimpleAdapter simpleAdapter;
public SimpleView(Context context, ViewGroup mviewGroup) {
super(context);
View layout = inflate(context, R.layout.test, mviewGroup);
listView = layout.findViewById(R.id.simple_list);
simpleAdapter = new SimpleAdapter(context, valueList);
listView.setAdapter(simpleAdapter);
}
public class SimpleAdapter extends BaseAdapter {
private LayoutInflater lInflater;
private String [] simpleValueList;
public SimpleAdapter(Context context, String[] simpleValueList) {
lInflater = LayoutInflater.from(context);
this.simpleValueList = simpleValueList;
}
#Override
public int getCount() {
return simpleValueList.length;
}
#Override
public Object getItem(int position) {
return simpleValueList[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.row, parent, false);
TextView textSimple = view.findViewById(R.id.txt);
textSimple.setText(simpleValueList[position]);
}
return view;
}
}
}
Sorry, I might have changed one or two of the names. I hope it does not cause any confusion.
Also, you can clean-up the layout. There are a few 'extra' LinearLayouts that I picked up from pasting in your code, but they are not really needed.
But this code is displaying 4 list items on my device.
I am trying to implement a cube animation on my viewPager. The animation looks good on the emulator and a Samsung S8 device, but on Huawei P10 Android 7.0 it looks like in the image below:
I don't understand why the image is cropped on my Huawei device. Below is my code:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ro.helpproject.funcode.help.MainActivity">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
view_pager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/imageView_mario"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#android:color/black"
android:src="#drawable/mario" />
CubeTransformer.java class
package ro.helpproject.funcode.help;
import android.support.v4.view.ViewPager;
import android.view.View;
public class CubeTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
view.setPivotX(position <= 0 ? view.getWidth(): 0.0f);
view.setRotationY(90f * position);
}
}
MainActivity.java
package ro.helpproject.funcode.help;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyViewPagerAdapter adapter = new MyViewPagerAdapter();
ViewPager pager = findViewById(R.id.pager);
pager.setPageTransformer(true, new CubeTransformer());
pager.setAdapter(adapter);
}
protected class MyViewPagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return 3;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
ImageView imageView = (ImageView) inflater.inflate(R.layout.view_pager_item, container, false);
container.addView(imageView);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
How can I fix the issue?
imageview.setAdjustViewBounds(true);
imageview.setFitToScreen(true);
imageview.setScaleType(ScaleType.FIT_XY);
update.....
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/imageView_mario"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:layout_gravity="center"
android:scaleType="fitXY"
android:background="#android:color/black"
android:src="#drawable/mario" />
The best way to achieve this is to add a parent to your imageView as follows:
<?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="horizontal"
android:gravity="center">
<ImageView
android:id="#+id/imageView_mario"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/black"
android:src="#drawable/mario" />
</LinearLayout>
Then in instantiateItem replace imageView with the LinearLayout:
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
LinearLayout linearLayout = (LinearLayout) inflater.inflate(R.layout.view_pager_item, container, false);
container.addView(linearLayout);
return linearLayout;
}
This should work properly.
The reason that your solution does not work is that the viewpager tries to fill it's "pages" with the imageview that you provide from your xml, and so it is stretched and has unexpected behaviour.
I've investigated several SO answers on this question (here, here, and here) and none of the proposed solutions have worked. My problem is that my RecyclerView list items aren't being displayed. I've set breakpoints in MessengerRecyclerAdapter, onCreateViewHolder, onBindViewHolder, and getItemCount and only the first one is ever called. While in a breakpoint I've entered the expression evaluator and executed
MessengerRecyclerAdapter.getItemCount();
And received the expected answer of 20. The RecyclerView itself takes up the intended content area as demonstrated by the screenshot below (I turned the RecyclerView magenta to highlight the space it occupies).
My RecyclerView XML code is below:
<?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.support.v7.widget.RecyclerView
android:id="#+id/thread_list"
android:background="#color/colorAccent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:name="com.jypsee.jypseeconnect.orgPicker.MessengerListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
tools:context="com.jypsee.jypseeconnect.orgPicker.MessengerListFragment"
tools:listitem="#layout/fragment_messenger_cell"/>
</LinearLayout>
My RecyclerView Cell XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#color/blueText"/>
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#color/darkText"/>
</LinearLayout>
My ListFragment class:
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
List<DummyContent.DummyItem> items = new ArrayList<>();
for (Integer i = 0; i<20; i++){
DummyContent.DummyItem item = new DummyContent.DummyItem(i.toString(),"Content","Details");
items.add(item);
}
View view = inflater.inflate(R.layout.fragment_messenger_list, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.thread_list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerAdapter = new MessengerThreadRecyclerAdapter(items, mListener);
mRecyclerView.setAdapter(mRecyclerAdapter);
mRecyclerAdapter.notifyDataSetChanged();
return view;
}
My Adapter class:
public class MessengerRecyclerAdapter
extends RecyclerView.Adapter<MessengerRecyclerAdapter.MessageThreadHolder>{
private final List<DummyItem> mValues;
private final RecyclerViewClickListener mListener;
public MessengerRecyclerAdapter(List<DummyItem> items, RecyclerViewClickListener listener) {
mValues = items;
mListener = listener;
}
#Override
public MessageThreadHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_messenger_cell, parent, false);
return new MessageThreadHolder(view);
}
#Override
public void onBindViewHolder(final MessageThreadHolder holder, final int position) {
holder.mItem = mValues.get(position);
holder.mIdView.setText(mValues.get(position).id);
holder.mContentView.setText(mValues.get(position).content);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
mListener.recyclerViewListClicked(v, position);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class MessageThreadHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final TextView mContentView;
public DummyItem mItem;
public MessageThreadHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content);
}
}
}
As you can see I've set the linearLayout orientation to vertical and set the layout manager, which were the 2 most common solutions. I'm really at a loss as to what to try next, so any help is appreciated.
As I said in previous Answer edit. The issues was in your xml. The main reason it was not showing was because, You were trying to add the fragment using include tag instead of fragment tag thus respective fragment class was never getting called on the fragment layout being added to your activity.
Below is the code you needed to add the Fragment correctly.
<fragment
android:id="#+id/message_thread"
android:name="com.jypsee.jypseeconnect.orgPicker.MessengerThreadListFragment"
layout="#layout/fragment_messengerthread_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_messengerthread_list" />
And your fragment layout should be like this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".orgPicker.MessengerThreadListFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/thread_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Here is the screenshot of working
In my case , I was missing calling notifyDataSetChanged() after setting list in adapter.
I'm trying to highlight background of one GridView element.
Activity.java:
private CustomAdapter ca;
public void onCreate(Bundle _) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
// ...
GridView gw = (GridView) findViewById(R.id.gridview);
gw.setAdapter(ca = new CustomAdapter(this));
gw.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// attempt 1:
view.setSelection(true);
// attempt 2:
gw.setSelection(position);
// attempt 3:
gw.setItemChecked(position, true);
// tried everything WITH and WITHOUT this:
ca.notifyDataSetChanged();
}
});
}
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
private LayoutInflater inflater;
public CustomAdapter(Context c) {
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Download items async, and call...
notifyDataSetChanged();
// ... in a callback
}
// getItem(), getCount() and getItemId() implemented here
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if( convertView!=null ) view = convertView;
else {
view = inflater.inflate(R.layout.grid_item, parent, false);
// calculate height so that an item is a square
int height = parent.getHeight();
if( height>0 ) {
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height/3;
}
}
ImageView image = (ImageView) view.findViewById(R.id.image);
image.setImageBitmap( getItemImageBitmap(position) );
return view;
}
}
activity_layout.xml
<GridView android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchMode="columnWidth"
android:numColumns="3"
android:drawSelectorOnTop="false"
android:choiceMode="singleChoice"
android:listSelector="#drawable/grid_selector"
/>
<!-- I've tried any combination of those last three params I could think of -->
grid_item.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/image"
android:background="#drawable/grid_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
grid_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#android:color/holo_red_dark" />
<item android:drawable="#android:color/transparent" />
</selector>
I tried putting grid_selector as item background OR as listSelector attribute in GridView.
My goal is to have one item highlighted upon user click (and after until other item is selected).
So the magic combination for me was:
gw.setItemChecked(position, true); in Activity.java is enough,
No changes in CustomAdapter.java,
listSelector="#drawable/grid_selector" MUST be removed from activity_layout.xml,
grid_item.xml must have background,
Use android:state_checked="true" instead of android:state_selected="true" in grid_selector.xml.
I try to change the background color at specific item within my ListView, while maintaining the effect of the custom Drawable.
My custom list_items :
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
style="#android:style/TextAppearance.Holo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background_list"
android:textColor="#color/white" />
My custom ArrayAdapter :
public class MissionDataListAdapter extends ArrayAdapter {
private final ArrayList<MissionData> list_missions;
public MissionDataListAdapter(Context context, int textViewResourceId, ArrayList<MissionData> objects) {
super(context, textViewResourceId, objects);
this.list_missions = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View v = super.getView(position, convertView, parent);
MissionData mission = list_missions.get(position);
if(position==4){
v.setBackgroundResource(R.color.mauve);
}
return v;
}
}
My Layout for my Activity :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/border_list"
android:orientation="vertical" >
<ListView
android:id="#+id/missionsListView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:divider="#color/blue2"
android:dividerHeight="1dp" />
</LinearLayout>
My custom drawable for change the color when item is pressed :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/orange_off" android:state_pressed="true"/>
</selector>
public class MissionsListActivity extends Activity implements OnClickListener {
[..]
MissionDataListAdapter arrayAdapter;
ArrayList<String> donnees_parses;
ArrayList<MissionData> missions;
ListView missionsListView;
MissionData selectedmission;
MissionsDAO missionsBdd;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.missions);
[..]
missionsListView = (ListView)this.findViewById(R.id.missionsListView);
int layoutID = R.layout.list_items;
arrayAdapter = new MissionDataListAdapter(this, layoutID , missions);
missionsListView.setAdapter(arrayAdapter);
}
[..]
For the above code, the background color of fourth item its changed, but is no longer affected by the custom Drawable :
[..]
<item android:drawable="#color/orange_off" android:state_pressed="true"/>
[..]
So, how can I change the background color of one item while maintaining the effects of Drawable on my item ?
Why not create another drawable with another color and then set that drawable if the position is 4:
#Override
public View getView(int position, View convertView, ViewGroup parent){
View v = super.getView(position, convertView, parent);
MissionData mission = list_missions.get(position);
if(position==4){
v.setBackgroundResource(R.drawable.background_list_mauve);
}
return v;
}