I have a dynamic array of drawables and want to display them in a scrollable list. The thing I am having the most trouble with is the array adapter. I don't get any compile time errors with this code, but the runtime error I get is -
Process: com.example.michael.myandroidappactivity, PID: 12297
java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
I don't want to use a textview though! Here's the main code-
public class cards extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_old_cards);
ListView list = (ListView)findViewById(R.id.showCardList);
cardPile tmp = cardPile.getInstance();
ArrayList<Integer> discardPile = tmp.getDiscardPile();
ArrayAdapter<Integer> imgAdapt = new ArrayAdapter<Integer>(this,R.layout.listview_layout,discardPile);
list.setAdapter(imgAdapt);
}
}
You have to create a new class that extends the BaseAdapter interface and modify the getView method to return the view you want to show in your ListView. For example:
public class ImageAdapter extends BaseAdapter
{
private Context context;
private ArrayList<Integer> imagesIds;
public ImageAdapter(Context _context, ArrayList<Integer> _imageIds)
{
context = _context;
imageIds = _imageIds;
}
#Override
public int getCount()
{
return imgIds.size();
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView view;
if( convertView != null ) // recycle call
{
view = (ImageView) convertView;
}
else
{
view = new ImageView(context);
image.setBackgroundResource(imageIds.get(position));
}
return view;
}
}
Then modify your listView adapter as:
list.setAdapter( new ImageAdapter( this, discardPile) );
Related
I have a list in which i can assigned the values statically.
private List<ListData> mDataList = Arrays.asList(
new ListData("Arun"),
new ListData("Jega"),
new ListData("Kabilan"),
new ListData("Karthick"),
new ListData("Joushva"),
new ListData("Niranjana"),
new ListData("Paramesh"),
new ListData("Prabha"),new ListData("Test1"),new ListData("Test2") );
The problem is now i got a scenario where i should get these value dynamically from web apim and i have to set it to the List variable mDataList.
Please help me to clear this. Thanks in advance.
Here is my complete code.
public class ReportFragment extends Fragment {
View ParentView;
private static final int HIGHLIGHT_COLOR = 0x999be6ff;
// list of data items
private List<ListData> mDataList = Arrays.asList(
new ListData("Arun"),
new ListData("Jega"),
new ListData("Kabilan"),
new ListData("Karthick"),
new ListData("Joushva"),
new ListData("Niranjana"),
new ListData("Paramesh"),
new ListData("Prabha"),new ListData("Test1"),new ListData("Test2")
);
// declare the color generator and drawable builder
private ColorGenerator mColorGenerator = ColorGenerator.MATERIAL;
private TextDrawable.IBuilder mDrawableBuilder;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ParentView= inflater.inflate(R.layout.report_fragment, container, false);
init();
return ParentView;
}
public void init(){
mDrawableBuilder = TextDrawable.builder()
.round();
// init the list view and its adapter
final ListView listView = (ListView) ParentView.findViewById(R.id.listView1);
listView.setAdapter(new SampleAdapter());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
}
private class SampleAdapter extends BaseAdapter {
#Override
public int getCount() {
return mDataList.size();
}
#Override
public ListData getItem(int position) {
return mDataList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(getActivity() , R.layout.list_item_layout, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ListData item = getItem(position);
// provide support for selected state
updateCheckedState(holder, item);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// when the image is clicked, update the selected state
ListData data = getItem(position);
data.setChecked(!data.isChecked);
updateCheckedState(holder, data);
}
});
holder.textView.setText(item.data);
return convertView;
}
private void updateCheckedState(ViewHolder holder, ListData item) {
if (item.isChecked) {
holder.imageView.setImageDrawable(mDrawableBuilder.build(" ", 0xff616161));
holder.view.setBackgroundColor(HIGHLIGHT_COLOR);
holder.checkIcon.setVisibility(View.VISIBLE);
}
else {
TextDrawable drawable = mDrawableBuilder.build(String.valueOf(item.data.charAt(0)), mColorGenerator.getColor(item.data));
holder.imageView.setImageDrawable(drawable);
holder.view.setBackgroundColor(Color.TRANSPARENT);
holder.checkIcon.setVisibility(View.GONE);
}
}
}
private static class ViewHolder {
private View view;
private ImageView imageView;
private TextView textView;
private ImageView checkIcon;
private ViewHolder(View view) {
this.view = view;
imageView = (ImageView) view.findViewById(R.id.imageView);
textView = (TextView) view.findViewById(R.id.textView);
checkIcon = (ImageView) view.findViewById(R.id.check_icon);
}
}
private static class ListData {
private String data;
private boolean isChecked;
public ListData(String data) {
this.data = data;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
}
}
}
create a method to add items in your adapter class, this method will add item to
itemlist. this will add items dynamically on your list or grid.
e.g
public void addItem(Item item){
itemList.add(item);
notifydatasetchanged();}
create a adapter class and constructor, in constructor just initialize the item arraylist and create extra method called addItem() this method will add item to your arraylist. after that you just have to call notifyDatasetchanged and your new item will be added.
I'm trying to display my recyclerView on MainActivity, but can't seem to do it.
This is my code: (which compiles with no errors)
private RecyclerView recyclerView;
private MyAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) this.findViewById(R.id.recycler_view_example);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyAdapter(this, getData());
recyclerView.setAdapter(adapter);
// Add Code to display recyclerView on Main...
}
// This is not my actual data, just testing it out
public static List<Block> getData() {
List<Block> data = new ArrayList<>();
String[] ids = {"310", "313", "320"};
String[] names = {"name of three ten", "name of three thirteen", "name of three twenty"};
for (int i=0; i<ids.length; i++) {
data.add(new Block(ids[i], names[i]));
}
return data;
}
And myActivity Class:
private final LayoutInflater inflater;
// Data: (information)
List<Block> data = new ArrayList<>();
public MyAdapter(Context context, List<Block> data) {
inflater = LayoutInflater.from(context);
this.data = data;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.block, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder h, int position) {
MyViewHolder holder = new MyViewHolder(h.itemView);
Block current = data.get(position);
holder.id.setText(current.getId());
holder.name.setText(current.getName());
}
#Override
public int getItemCount() {
return 0;
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView id;
TextView name;
Button button;
// Constructor
public MyViewHolder(View itemView) {
super(itemView);
id = (TextView) itemView.findViewById(R.id.the_course_id);
name = (TextView) itemView.findViewById(R.id.course_name);
button = (Button) itemView.findViewById(R.id.click);
}
}
}
All I'm trying to do now is that when I run the emulator, I will see the contents of the recyclerView. But, I've been stuck on this for a while as nothing seems to work.
Mind you I'm a beginner with Android, so forgive me if this is very trivial.
You should return the number of items in your list, within getItemCount as in:
#Override
public int getItemCount() {
return data.size();
}
Ok here you need to change the following: update -
recyclerView.setLayoutManager(new LinearLayoutManager(this));
to
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
and in adapter class change:
#Override
public int getItemCount() {
return data.size();
}
thats it. Happy coding :)
Change onBindViewHolder to:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder h, int position) {
Block current = data.get(position);
h.id.setText(current.getId());
h.name.setText(current.getName());
}
also add #SelçukCihan solution to this
EDIT
Also if you want to use your MyViewHolder you have to change the following:
First change class signature:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
and also change the signature for onBindViewHolder:
public void onBindViewHolder(MyViewHolder h, int position)
and finally change the signature of your MyViewHolder class:
static class MyViewHolder extends RecyclerView.ViewHolder
In my app I have PostersFragment that will be a GridView with movies posters, in this fragment I need to initialize the GridView and customGridViewAdapter.
My customGridViewAdapter need to get the Bitmaps array and then work with it.
The problem that I call to AsyncTask that is in different class that gets all information from JSON and stores the information with the movies posters on local database.
I cant understand how and when to use the .setAdapter(gridViewCustomAdapter);
There is my code.
public class PostersFragment extends Fragment implements AdapterView.OnItemClickListener {
private GridView gv_posters;
private GridViewCustomAdapter gridViewCustomAdapter;
public PostersFragment() {
setHasOptionsMenu(true);
}
#Override
public void onStart() {
super.onStart();
UpdatePosters();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("TESTAG","onCreateView");
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
gv_posters = (GridView) rootView.findViewById(R.id.gv_posters);
gv_posters.setAdapter(gridViewCustomAdapter);
gv_posters.setOnScrollListener(new PostersScrollListener(getActivity().getApplicationContext()));
gv_posters.setOnItemClickListener(this);
// Define new adapter for grid view
return rootView;
}
private void UpdatePosters() {
Log.d("TESTAG","UpdatePoster");
MoviesTask task = new MoviesTask(getActivity(),gridViewCustomAdapter);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String path = prefs.getString(getString(R.string.sort_method_posters_pref), getString(R.string.default_path));
task.execute(path);
}
MoviesTask.java
public class MoviesTask extends AsyncTask<String, Void, Bitmap[]> {
// Byte array to handle bitmaps
private byte[] imgByte;
// Context and custom adapter variables
private final Context mContext;
private GridViewCustomAdapter mGridCustomAdapter;
// MovieTask Constructor
public MoviesTask(Context context, GridViewCustomAdapter gridAdapter) {
mContext = context;
mGridCustomAdapter = gridAdapter;
}
Parsing JSON methods...
#Override
protected void onPostExecute(Bitmap[] bitmaps){
Log.d("TESTAG","onPostExecute");
if (bitmaps != null)
mGridCustomAdapter = new GridViewCustomAdapter(mContext,R.id.single_gv_poster,bitmaps);
}
GridViewCustomAdapter.java
public class GridViewCustomAdapter extends BaseAdapter{
private Context context;
int layoutResource;
private Bitmap[] bitmaps;
public GridViewCustomAdapter(Context context,int layoutResource, Bitmap[] bitmaps){
this.context = context;
this.layoutResource = layoutResource;
this.bitmaps = bitmaps;
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
viewHolder holder = null;
if (view == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
view = inflater.inflate(layoutResource,parent,false);
holder = new viewHolder();
holder.imageView = (ImageView)view.findViewById(R.id.single_gv_poster);
view.setTag(holder);
}else
holder = (viewHolder)view.getTag();
Bitmap bitmap = bitmaps[position];
holder.imageView.setImageBitmap(bitmap);
return view;
}
static class viewHolder{
ImageView imageView;
}
}
Anyone can help me with this issue please?
You can do this way:
Delete line from onCreate():
gv_posters.setAdapter(gridViewCustomAdapter);
Your PostExecute should looks like this:
#Override
protected void onPostExecute(Bitmap[] bitmaps){
Log.d("TESTAG","onPostExecute");
if (bitmaps != null)
mGridCustomAdapter = new GridViewCustomAdapter(mContext,R.id.single_gv_poster,bitmaps);
gv_posters.setAdapter(mGridCustomAdapter);
}
}
Hope this will help you.
have gridview for which set adapter called ImageAdapter with parameter of arraylist. Inside the adapter have onclicklistener during which from the arraylist one item is removed and then when i use this line ImageAdapter.notifyDataSetChanged in the gridview item is removed. Now i need the changed arrayList in my activity so how can i get it.
Here's my code:
public class ImageAdapter extends BaseAdapter {
Context context;
ArrayList<String> listCheck = new ArrayList<String>();
ImageAdapter adapter = this;
public ImageAdapter(Context context, ArrayList<String> list) {
this.context = context;
listCheck = list;
}
#Override
public int getCount() {
return listCheck.size();
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder121 holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(
R.layout.item_gridmain, null);
holder = new ViewHolder121();
holder.imageView = (ImageView) convertView
.findViewById(R.id.img_selected_image);
holder.close = (ImageButton) convertView
.findViewById(R.id.img_btn_cancel);
convertView.setTag(holder);
}
else {
holder = (ViewHolder121) convertView.getTag();
}
holder.close.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg1) {
listCheck.remove(position);
adapter.notifyDataSetChanged();
}
}); Bitmap bm = decodeSampledBitmapFromUri(listCheck.get(position), 220,
220);
holder.imageView.setImageBitmap(bm);
return convertView;
} }
Fragment code:
ImageAdapter mainActivityAdapter = new ImageAdapter(getActivity(), ar1);
gridview_withimage.setAdapter(mainActivityAdapter);
question: How to get changed arraylist from ImageAdapter to called Fragement
How to get changed arraylist from ImageAdapter to called Fragement
Create a method in ImageAdapter which will return ArrayList used as data-source in Adapter:
public ArrayList<String> getModifyList() {
return listCheck;
}
Call getModifyList method in Fragment for getting ArrayList using Adapter object:
gridview_withimage.setAdapter(mainActivityAdapter);
gridview_withimage.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
ArrayList<String> arrNewList=mainActivityAdapter.getModifyList();
}
}, 100);
You can pass Fragment instance to Adapter.
private Fragment fragment;
public ImageAdapter(Context context, ArrayList<String> list,Fragment mfragment) {
this.context = context;
listCheck = list;
this.fragment=mfragment;
}
and Make one public method in your fragment and call using this instance of Fragment fragment;
You can create an interface like this
public interface ImageAdapterListener{
void onListChange(List<String> list);
}
And declare a member in ImageAdapter
private ImageAdapterListener listener;
public setListener(ImageAdapterListener listener){
this.listener = listener}
override the notifyDataSetChanged
#Override
void notifyDataSetChanged{
super.notifyDataSetChanged();
if(listener!= null) listener.onListChange(listCheck);
}
and make your fragment implement that interface.
class Myfragment extends Fragment implements ImageAdapterListener {
ImageAdapter mainActivityAdapter = new ImageAdapter(getActivity(), ar1);
gridview_withimage.setAdapter(mainActivityAdapter);
mainActivityAdapter.setListener(this);
#Override
void onListChange(List<String> list){
//do your stuff
}
}
I'm trying to inflate a list using baseadapter within an activity. The list just doesn't inflate. From the logs implemented within the class, the getView() function doesn't even execute. Here's the code. -
public class CallLog extends Activity {
ListView logList;
List mList;
Context mCtx;
ArrayList<String> logName;
ArrayList<String> logNumber;
ArrayList<String> logTime;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.reject_call_log);
mCtx = getApplicationContext();
ListView logList = (ListView) findViewById(R.id.log_list);
mList = new List(mCtx, R.layout.log_row);
logList.setAdapter(mList);
SharedPreferences savedLogName = PreferenceManager.getDefaultSharedPreferences(mCtx);
SharedPreferences savedLogNumber = PreferenceManager.getDefaultSharedPreferences(mCtx);
SharedPreferences savedLogTime = PreferenceManager.getDefaultSharedPreferences(mCtx);
try{
logName = new ArrayList(Arrays.asList(TextUtils.split(savedLogName.getString("logName", null), ",")));
logNumber = new ArrayList(Arrays.asList(TextUtils.split(savedLogNumber.getString("logNumber", null), ",")));
logTime = new ArrayList(Arrays.asList(TextUtils.split(savedLogTime.getString("logTime", null), ",")));
Collections.reverse(logName);
Collections.reverse(logNumber);
Collections.reverse(logTime);
}catch(NullPointerException e){
e.printStackTrace();
//TextView noLog = (TextView)findViewById(R.id.no_log);
}
}
public class List extends BaseAdapter {
LayoutInflater mInflater;
TextView nameText;
TextView numberText;
TextView timeText;
int timePos = 1;
public List(Context context, int resource) {
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (convertView == null) {
v = mInflater.inflate(R.layout.row, null);
}
nameText = (TextView) v.findViewById(R.id.log_name);
numberText = (TextView) v.findViewById(R.id.log_number);
timeText = (TextView) v.findViewById(R.id.log_time);
nameText.setText(logName.get(position));
numberText.setText(logNumber.get(position));
timeText.setText(logTime.get(timePos) + logTime.get(timePos+1));
Log.d("RejectCall", "ListView");
timePos+=2;
return v;
}
}
}
Where is it all going wrong? Also, is there a better way to do what I'm trying to do?
Please replace the following code :
#Override
public int getCount() {
return 0;
}
with
#Override
public int getCount() {
return logName.size();
}
As list view only show the numbers of rows that is returned by this method and right now you are returning 0;
And after fetching the data in arraylist please use adapter.notifyDataSetChanged() to notify the list view.
You have to call notifyDataSetChanged() as you are filling data in array list after setting the adapter. so to notify the list view that data has been changed you have to call notify method(as above)
Your getItem() and getCount() haven't been implemented. If you want any kind of adapter to work for the list, these need to be implemented. Your list is also not holding any actual data, so getItem() has nothing to set.
Don't forget to call notifiyDataSetChanged() in your adapter after you set appropriate implementations for the above two functions.