I followed all the steps from various sources for getting listviews to work but my one
doesn't seem to display anything. This list view code(shown below) is activated with a tab fragment manager I won't put that here as to not bog you all down with code as there's a lot here already. It is most likely a problem with the ListFragment itself but I suppose it could be the adapter.
What happens is nothing gets displayed at all just the searchview that I have put in the main xml layout. I can switch freely between tabs with no crashes but just nothing displays in any of my listviews. I have another list which is a friends list(not included in this code snippet) and that uses a generic view holder interface and that one does not work either which suggests the problem is most likely in my ListFragment but I just can't pinpoint it. Any help is appreciated and I hope some can learn something from this, Thank you.
This is my adapter for the settings category list
package codeblox.com.listfragmentexample;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;
import java.util.ArrayList;
import codblox.com.listfragmentexample.R;
public class SettingsAdapter extends ArrayAdapter<Settings.SettingsCategories>
{
private final Activity context;
String[] text;
ArrayList<Settings.SettingsCategories> itemsCopy;
class ViewHolder
{
public TextView txt;
public CheckBox state;
public ImageView settingImg;
public EditText input;
public ToggleButton toggle;
public Button settingInfo; // click it to show what the setting does
}
public SettingsAdapter(Context context, ArrayList<Settings.SettingsCategories> items)
{
super(context, R.layout.settings_category_row, items);
this.context = (Activity) context;
this.itemsCopy = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = new ViewHolder();
int viewType = this.getItemViewType(position);
if(convertView == null)
{
// inflate the GridView item layout
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.settings_category_row, parent, false);
// initialize the view holder
holder = new ViewHolder();
holder.settingImg = (ImageView) convertView.findViewById(R.id.settingCategoryImg);
holder.txt = (TextView) convertView.findViewById(R.id.settingCategoryName);
convertView.setTag(holder);
} else {
// recycle the already inflated view
holder = (ViewHolder) convertView.getTag();
}
// fill data
holder = (ViewHolder) convertView.getTag();
String s = getItem(position).toString();
holder.txt.setText(itemsCopy.get(position).getSettingText());
holder.settingImg.setImageResource(itemsCopy.get(position).getImgResId());
return convertView;
}
}
This is my list fragment
package codeblox.com.listfragmentexample
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import codeblox.com.listfragmentexample.R;
public class Settings extends ListFragment implements View.OnLongClickListener
{
private ListView settingsList;
private ArrayList<SettingsCategories> mItems;
private ArrayAdapter<SettingsCategories> settingsAdapter;
private int numCategories;
String[] CategoryArray = new String[] {"Privacy and Security","Account","Networks","Camera Options","Storage","Accesibility","Features"};
int[] resIds = new int[] {R.drawable.security_settings_icon,R.drawable.account_settings_icon,
R.drawable.network_settings_icon,R.drawable.camera_settings_icon,R.drawable.storage_settings_icon,
R.drawable.accessibility_settings_icon,R.drawable.feature_settings_icon,};
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View settingsView = inflater.inflate(R.layout.settings, container, false);
settingsList = (ListView)settingsView.findViewById(android.R.id.list);
// initialize the items list
return settingsView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
// remove the dividers from the ListView of the ListFragment
settingsList = getListView();
settingsList.setDivider(null);
mItems = new ArrayList<SettingsCategories>();
Resources resources = getResources();
for(int c = 0; c < numCategories; c++)
{
mItems.add(new SettingsCategories(CategoryArray[c],resIds[c]));
}
// initialize and set the list adapter
// settingsAdapter = new SettingsAdapter(this.getActivity(), mItems);
setListAdapter(new SettingsAdapter(getActivity(), mItems));
settingsList.setAdapter(settingsAdapter);
}
public Settings()
{
this.numCategories = CategoryArray.length;
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#Override
public boolean onLongClick(View v)
{
return false;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id)
{
Object i = l.getItemAtPosition(position);
}
public class SettingsCategories
{
private String settingText;
private int imgResId;
SettingsCategories(String settingText,int imgResId)
{
this.settingText = settingText;
this.imgResId = imgResId;
}
public String getSettingText()
{
return this.settingText;
}
public int getImgResId()
{
return this.imgResId;
}
}
}
and finally these are my xml layouts (the first one is the main view and the second one is the view of a single item in the list
<?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="fill_parent"
android:orientation="vertical"
>
<SearchView
android:id="#+id/searchFunction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</SearchView>
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</RelativeLayout>
this represents an individual item in the list
<?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="match_parent"
>
<ImageView
android:layout_width="52dp"
android:layout_height="52dp"
android:id="#+id/settingCategoryImg"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="52dp"
android:text=""
android:id="#+id/settingCategoryName"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/settingCategoryImg"
/>
</RelativeLayout>
You are setting null adapter so it is not refreshing.
you are commented initialization part
check in the following method:
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
// remove the dividers from the ListView of the ListFragment
settingsList = getListView();
settingsList.setDivider(null);
mItems = new ArrayList<SettingsCategories>();
Resources resources = getResources();
for(int c = 0; c < numCategories; c++)
{
mItems.add(new SettingsCategories(CategoryArray[c],resIds[c]));
}
// initialize and set the list adapter
// settingsAdapter = new SettingsAdapter(this.getActivity(), mItems);
setListAdapter(new SettingsAdapter(getActivity(), mItems));
settingsList.setAdapter(settingsAdapter);
}
Your are using ListFragement and again inflating layout. that is not a good idea. when you are extending listfragment then inflating the layout is not required and and modify above method like:
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
// remove the dividers from the ListView of the ListFragment
settingsList = getListView();
settingsList.setDivider(null);
mItems = new ArrayList<SettingsCategories>();
Resources resources = getResources();
for(int c = 0; c < numCategories; c++)
{
mItems.add(new SettingsCategories(CategoryArray[c],resIds[c]));
}
// initialize and set the list adapter
settingsAdapter = new SettingsAdapter(this.getActivity(), mItems);
//setListAdapter(new SettingsAdapter(getActivity(), mItems));
settingsList.setAdapter(settingsAdapter);
}
Related
I want to inflate a slider and a recycler view programatically in a fragment.
The Slider gets inflated successfully and the swipe refresh also is functioning.
NO ERROR IN THE LOG BUT THE RECYLER VIEW DOESN'T GET INFLATED
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View fragmentView = inflater.inflate(R.layout.fragment_conversation, container, false);
RelativeLayout fragmentRelativeLayout = (RelativeLayout)fragmentView.findViewById(R.id.conversation_fragment_main);
View header = LayoutInflater.from(getActivity()).inflate(R.layout.slider, container, false);
View recylerList = LayoutInflater.from(getActivity()).inflate(R.layout.news_layout_recyler_view,container,false);
headerSlider = (SliderLayout)header.findViewById(R.id.slider);
TextSliderView textSliderView = new TextSliderView(getActivity().getApplicationContext());
// initialize a SliderLayout
textSliderView
.description("Hello")
.image("http://media2.intoday.in/indiatoday/images/stories/pawan-kalyan-story-650_010215012726.jpg")
.setScaleType(BaseSliderView.ScaleType.Fit)
.setOnSliderClickListener(this);
//add your extra information
textSliderView.bundle(new Bundle());
textSliderView.getBundle()
.putString("extra", "POWER STAR");
headerSlider.addSlider(textSliderView);
headerSlider.setPresetTransformer(SliderLayout.Transformer.Accordion);
headerSlider.setPresetIndicator(SliderLayout.PresetIndicators.Center_Bottom);
headerSlider.setCustomAnimation(new DescriptionAnimation());
headerSlider.setDuration(4000);
headerSlider.addOnPageChangeListener(this);
fragmentRelativeLayout.addView(header);
fragmentRelativeLayout.addView(recylerList);
newsList = (RecyclerView)recylerList.findViewById(R.id.listNews);
//newsList = (RecyclerView) recylerList.findViewById(R.id.listNews);
newsList.addItemDecoration(new DividerItemDecoration(getActivity(),DividerItemDecoration.VERTICAL_LIST));
callBackListener = this;
newsListObject = retrieveFromLocalDb.retrieveNewsList();
// Initializing Swipe To Refresh Layout
//swipeToRefreshNewsList = (SwipeRefreshLayout)fragmentView.findViewById(R.id.swipeToRefreshNews);
swipeToRefreshNewsList = (SwipeRefreshLayout) recylerList.findViewById(R.id.swipeToRefreshNews);
swipeToRefreshNewsList.setOnRefreshListener(this);
adapter = new recylerViewNewsAdapter(getActivity(),newsListObject);
if(newsListObject.isEmpty()) {
new loadNewsListInBackground(this).execute();
}
adapter.setNewsDataList((ArrayList<newsModelStore>) newsListObject);
newsList.setAdapter(adapter);
newsList.setLayoutManager(new LinearLayoutManager(getActivity()));
return fragmentView;
}
The news_layout_recyler_view.xml
<RelativeLayout 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="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipeToRefreshNews"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listNews"
>
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
I am pretty sure that the data is retrieved as I can see in the debug log. I don't know why it is not showing up. The adapter is as follows :
package com.example.prabhukonchada.fanstationmvp;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by prabhukonchada on 26/11/15.
*/
public class recylerViewNewsAdapter extends RecyclerView.Adapter<recylerViewNewsAdapter.newsListViewHolder> {
List<newsModelStore> newsModelStoreList = Collections.emptyList();
private LayoutInflater inflater;
Context context;
public recylerViewNewsAdapter(Context context,List<newsModelStore> newsModelStoreList)
{
this.newsModelStoreList = newsModelStoreList;
inflater = LayoutInflater.from(context);
this.context = context;
}
#Override
public newsListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.news_layout,parent,false);
newsListViewHolder newsHolder = new newsListViewHolder(view);
return newsHolder;
}
#Override
public void onBindViewHolder(newsListViewHolder holder, int position) {
holder.newsInformation.setText(newsModelStoreList.get(position).getNewsInformation());
if(newsModelStoreList.get(position).getImageUrl()!= null) {
Picasso.with(context).load(newsModelStoreList.get(position).getImageUrl()).into(holder.newsImage);
}else
{
Drawable userImageDrawable = context.getResources().getDrawable(R.drawable.super_user);
holder.newsImage.setImageDrawable(userImageDrawable);
}
}
#Override
public int getItemCount() {
return 0;
}
class newsListViewHolder extends RecyclerView.ViewHolder
{
TextView newsInformation;
ImageView newsImage;
TextView timeStatus;
ImageView awesome;
TextView awesomenessCount;
View view;
public newsListViewHolder(View itemView)
{
super(itemView);
newsInformation = (TextView)itemView.findViewById(R.id.newsInformation);
newsImage = (ImageView)itemView.findViewById(R.id.newsImage);
// timeStatus = (TextView)itemView.findViewById(R.id.started_timestamp);
// awesome = (ImageView)itemView.findViewById(R.id.awesomeImage);
// awesomenessCount = (TextView)itemView.findViewById(R.id.awesomenessCount);
}
}
public void setNewsDataList(ArrayList<newsModelStore> newsModelStoreList)
{
this.newsModelStoreList = newsModelStoreList;
notifyDataSetChanged();
}
}
It's no wonder, you return that recycler view adapter has no records:
#Override
public int getItemCount() {
return 0;
}
Change it to newsModelStoreList.size()
I am using ListView with ArrayAdapter and trying to add fragments to all rows of the ListView. However, the app does not work correctly: only one row on the screen showed with the added fragment but not all rows. Sometimes the app may be crashed because out of memory.
Can someone give me some advices? Thanks.
MainActivity.java
package com.me.test05;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
ListView myListView = (ListView) findViewById(R.id.myListView);
myListView.setAdapter(new MyArrayAdaptor(this, R.layout.row));
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
private static final String[] allnames = { "John", "Marry", "Smith", "Felicity", "Lion", "Math" };
public static class MyArrayAdaptor extends ArrayAdapter<String> {
private final Context context;
public MyArrayAdaptor(Context context, int resource) {
super(context, resource);
this.context = context;
}
#Override
public int getCount() {
return allnames.length * 100;
}
#Override
public String getItem(int position) {
return allnames[position % allnames.length];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.textView1);
String str = getItem(position);
textView.setText(str);
FragmentTransaction ft = ((Activity) context).getFragmentManager().beginTransaction();
ft.replace(R.id.myFrameLayout, new PlaceholderFragment());
ft.commit();
return rowView;
}
}
}
File activity.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:fitsSystemWindows="true">
<ListView android:id="#+id/myListView"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:dividerHeight="2px">
</ListView>
</merge>
File row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="abc" />
<FrameLayout
android:id="#+id/myFrameLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</FrameLayout>
</LinearLayout>
File fragment_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView1"
android:layout_below="#+id/textView1"
android:text="Button" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
Screen looks like:
I have solved that problem. The problem is the fragment manager always find (to replace by a new fragment) an id in global. That is why it always found and added all new fragments into the first row since it is the first one contains that id (as well as all other rows).
To solve the problem, I create dynamic ids which are unique for each row then replace that fixed id by them before letting fragment manager to do the rest. I also store those dynamic ids into rows' tags to reuse latter.
The new code is bellow, including the code for finding and reusing added fragments:
package com.me.test05;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
ListView myListView = (ListView) findViewById(R.id.myListView);
myListView.setAdapter(new MyArrayAdaptor(this, R.layout.row));
}
}
public static class PlaceholderFragment extends Fragment {
private View rootView = null;
private String theString = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_main, container, false);
setString(theString);
return rootView;
}
public void setString(String str) {
theString = str;
if (theString != null && rootView != null) {
TextView textView = (TextView) rootView.findViewById(R.id.textView2);
textView.setText(str);
}
}
}
private static final String[] allnames = { "John", "Marry", "Smith", "Felicity", "Lion", "Math" };
public static class MyArrayAdaptor extends ArrayAdapter<String> {
private final Context context;
public MyArrayAdaptor(Context context, int resource) {
super(context, resource);
this.context = context;
}
#Override
public int getCount() {
return allnames.length * 100;
}
#Override
public String getItem(int position) {
return allnames[position % allnames.length];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = convertView;
PlaceholderFragment myFragment = null;
if (rowView == null) {
rowView = inflater.inflate(R.layout.row, parent, false);
int newId = 100000 + position;
FrameLayout layout = (FrameLayout) rowView.findViewById(R.id.myFrameLayout);
layout.setId(newId);
rowView.setTag(newId);
myFragment = new PlaceholderFragment();
FragmentTransaction ft = ((Activity) context).getFragmentManager().beginTransaction();
ft.replace(newId, myFragment, "" + newId).commit();
} else {
Integer theId = (Integer) convertView.getTag();
myFragment = (PlaceholderFragment) ((Activity) context).getFragmentManager().findFragmentById(theId);
}
String str = getItem(position);
myFragment.setString(str + ", " + position);
TextView textView = (TextView) rowView.findViewById(R.id.textView1);
textView.setText(str);
return rowView;
}
}
}
I am learning to make a simple time table managing application.
I have a list of courses displayed. Each item in a list is a textview + a delete button. The onClick Listener in my list item isn't working as expected. When I click on the delete button, it is working fine. However, I want to open up some other activity when user clicks on the textview of the list item.
Code:
ShowAll.java (the main activity in which I am displaying a list of classes)
package com.example.android.mytimetable;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class ShowAll extends ActionBarActivity {
private ArrayAdapter<String> adapter ;
ArrayList <ClassDetail> classesDetail ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_all);
this.bindAdapter();
ListView listView = (ListView) this.findViewById(R.id.class_list);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.v("Item", "clicked");
Intent intent = new Intent(view.getContext(), ShowAllClicked.class);
ClassDetail classDetail = classesDetail.get(i);
Bundle bundle = new Bundle();
bundle.putString("CLASS_NAME", classDetail.class_name);
bundle.putString("BUILDING", classDetail.building);
bundle.putString("MONDAY_START", classDetail.monday_start);
bundle.putString("MONDAY_END", classDetail.monday_end);
bundle.putString("TUESDAY_START", classDetail.tuesday_start);
bundle.putString("TUESDAY_END", classDetail.tuesday_end);
bundle.putString("WEDNESDAY_START", classDetail.wednesday_start);
bundle.putString("WEDNESDAY_END", classDetail.wednesday_end);
bundle.putString("THURSDAY_START", classDetail.thursday_start);
bundle.putString("THURSDAY_END", classDetail.thursday_end);
bundle.putString("FRIDAY_START", classDetail.friday_start);
bundle.putString("FRIDAY_END", classDetail.friday_end);
intent.putExtras(bundle);
startActivity(intent);
}
});
}
void bindAdapter() {
DBHelper db = new DBHelper(this);
classesDetail = db.getClassesDetail();
ArrayList <String> classes = new ArrayList<>();
for(int i = 0 ; i < classesDetail.size() ; i++) {
Log.v("Adding ", classesDetail.get(i).class_name);
classes.add(classesDetail.get(i).class_name);
}
if(classes.size() == 0)
((TextView) this.findViewById(R.id.holiday)).setText(getString(R.string.noClass));
CustomArrayAdapter customArrayAdapter = new CustomArrayAdapter(classes, this);
((ListView) this.findViewById(R.id.class_list)).setAdapter(customArrayAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_show_all, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return super.onOptionsItemSelected(item);
}
}
activity_show_all.xml (the xml layout of ShowAll.java)
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.android.mytimetable.ShowAll"
android:orientation="vertical">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/class_list"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/holiday"/>
</LinearLayout>
CustomArrayAdapter.java (The custom array adapter file)
package com.example.android.mytimetable;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by Aman Goel on 02-08-2015.
*/
public class CustomArrayAdapter extends BaseAdapter implements ListAdapter {
private ArrayList <String> list = new ArrayList<String>();
private Context context;
public CustomArrayAdapter(ArrayList <String> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
((TextView) view.findViewById(R.id.list_item)).setText(list.get(position));
Button deleteBtn = (Button) view.findViewById(R.id.delete);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DBHelper db = new DBHelper(context);
db.deleteClass(list.get(position));
list.remove(position);
notifyDataSetChanged();
}
});
return view;
}
}
list_item.xml (The layout of each list view)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:id="#+id/list_item"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/delete"
android:id="#+id/delete"/>
</LinearLayout>
I tried to take help from here: Set onClickListener into custom adapter and here: Where should I place the onClickListener on a Custom ListView?
However, I am still not able to make the adapter work. Any help would be appreciated
set on custom adapter getview function
TextView lst_tv=(TextView)view.findViewById(R.id.list_item);
lst_tv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
customArrayAdapter.setOnItemClickListener(...)
I am trying to display a custom listview but nothing appears.
My activity:
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import com.example.elnoorgeh.ServerAPI;
import android.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView.FindListener;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
public class BlogFragment extends Fragment {
JSONArray jArray;
TextView title;
RelativeLayout layout;
int previousID = 0;
int currentID = 0;
ArrayList<String> titles;
ArrayList<String> contents;
ListView list;
public BlogFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_blog, container,
false);
new AsyncFetch().execute();
return rootView;
}
private class AsyncFetch extends AsyncTask<Object, Object, Object> {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
jArray = new JSONArray();
jArray = ServerAPI.getData();
titles = new ArrayList<String>();
contents = new ArrayList<String>();
for (int i = 0; i < jArray.length(); i++) {
String blogTitle = null;
String content = null;
try {
blogTitle = jArray.getJSONObject(i).getString("title");
content = jArray.getJSONObject(i).getString("content");
titles.add(blogTitle);
contents.add(content);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(blogTitle);
System.out.println(content);
}
// display(titles, contents);
return null;
}
protected void onPostExecute(Object result) {
layout = (RelativeLayout) getView().findViewById(R.id.blogPage);
layout.removeAllViews();
CustomList adapter = new CustomList(getActivity(), titles);
list = new ListView(getActivity());
System.out.println("list done");
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(),
"You Clicked at " + titles.get(position),
Toast.LENGTH_SHORT).show();
}
});
}
}
public void display(ArrayList<String> t, ArrayList<String> c) {
}
}
Custom ListView class:
import java.util.ArrayList;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomList extends ArrayAdapter<String> {
private final Activity context;
private final ArrayList<String> web;
// private final Integer[] imageId;
public CustomList(Activity context, ArrayList<String>web) {
super(context, R.layout.fragment_listview);
this.context = context;
this.web = web;
// this.imageId = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.fragment_listview, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
txtTitle.setText((CharSequence) web.get(position));
// imageView.setImageResource(imageId[position]);
return rowView;
}
}
fragment_blog:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/blogPage"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
<TextView
android:id="#+id/txtLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:maxLines="20"
android:singleLine="false"
android:textSize="16dp" />
</RelativeLayout>
fragment_listview:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<ImageView
android:id="#+id/img"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="50dp" />
</TableRow>
</TableLayout>
I can't find any errors or notice something irregular, so why is that happening?
you should extend BaseAdapter and implement abstract methods
#Override
public int getCount() {
return web.size();
}
#Override
public Object getItem(int position) {
return web.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
also you might change
txtTitle.setText((CharSequence) web.get(position));
to
txtTitle.setText((CharSequence) getItem(position));
now your adapter don't know size of web array
edit:
you can get one inflater in constructor and keep in class, no need to getting inflater each time (little bit better for perfomance)
LayoutInflater inflater = context.getLayoutInflater();
edit 2:
localhost put proper comment - you are removing all Views from RelativeLayout, also ListView, and creating new ListView without adding to Relative. keeping reference will not auto-add View
protected void onPostExecute(Object result) {
layout = (RelativeLayout) getView().findViewById(R.id.blogPage);
layout.removeView(getView().findViewById(R.id.txtLabel);
//assuming you need to remove only txtLabel
CustomList adapter = new CustomList(getActivity(), titles);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(),
"You Clicked at " + titles.get(position),
Toast.LENGTH_SHORT).show();
}
});
}
I have a custom ArrayAdapter which contains a text and an image, but somehow the items don't show in the list.
This is my custom adapter:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class DrawerArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] entries;
private final Integer[] imageIds;
public DrawerArrayAdapter(Context context, String[] entries, Integer[] imageIds) {
super(context, R.layout.drawer_list_item, entries);
this.context = context;
this.entries = entries;
this.imageIds = imageIds;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.drawer_list_item, parent, false);
TextView entryView = (TextView) rowView.findViewById(R.id.drawer_list_entry);
ImageView iconView = (ImageView) rowView.findViewById(R.id.drawer_list_icon);
entryView.setText(entries[position]);
iconView.setImageResource(imageIds[position]);
return rowView;
}
}
And this is the Fragment:
import android.app.ListFragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class DrawerFragment extends ListFragment {
private String[] drawerListEntries;
private DrawerLayout drawerLayout;
private Integer[] drawerListIcons;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawerListIcons = new Integer[] {R.drawable.ic_action_user,R.drawable.ic_action_user,R.drawable.ic_action_user,R.drawable.ic_action_user};
drawerListEntries = getResources().getStringArray(R.array.drawer_items);
setListAdapter(new DrawerArrayAdapter(getActivity(), drawerListEntries, drawerListIcons));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.drawer_fragment, container, false);
}
#Override
public void onStart() {
super.onStart();
drawerLayout = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(getActivity(),
getListView().getItemAtPosition(position).toString(),
Toast.LENGTH_LONG).show();
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
//boolean drawerOpen = drawerLayout.isDrawerOpen(drawerList);
//menu.findItem(R.id.action_user).setVisible(!drawerOpen);
super.onPrepareOptionsMenu(menu);
}
}
and this is my drawer_list_item.xml :
<?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="70dp"
android:padding="5dp"
android:orientation="vertical" >
<TextView
android:id="#+id/drawer_list_entry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="12dp"
android:paddingLeft="20dp"
android:paddingBottom="20dp"
android:paddingTop="20dp"
android:textSize="24sp"
android:textColor="#color/light_blue"
android:fontFamily="sans-serif-light" >
</TextView>
<ImageView
android:id="#+id/drawer_list_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/drawer_icon">
</ImageView>
</LinearLayout>
I should probably mention that when I just use a normal ArrayAdapter with just text, it works perfectly. Anyone seeing the problem?
You really don't want to inflate new views for every row in your custom adapter's getView() ignoring the provided convertView. ListViews don't use 1000 separate views when you have 1000 rows in the adapter, views get recycled.
So I would simply call:
View view = super.getView(position, convertView, parent);
and then use view.findViewById() to set the data on your individual sub-views before returning the view that the ArrayAdapter returned. The ArrayAdapter already takes care of re-using recycled views.
Note that ArrayAdapter already sets the TextView itself, so you only need to set the ImageView, but for that the ArrayAdapter will need to know the id of your TextView, so use the constructor:
super(context, R.layout.drawer_list_item, R.id.drawer_list_entry, entries);
Because views are recycled make sure to always set the ImageView source. If a particular row has no image you need to clear it rather than do nothing.
EDIT: Another problem was related to the row layout. The vertical margin and padding was too much for the limited vertical row height of 70dp.
EDIT: Here an example of the adapter.
public class DrawerArrayAdapter extends ArrayAdapter<String> {
private final Integer[] mImageIds;
public DrawerArrayAdapter(Context context, String[] entries, Integer[] imageIds) {
super(context, R.layout.drawer_list_item, R.id.drawer_list_entry, entries);
mImageIds = imageIds;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = super.getView(position, convertView, parent);
((ImageView)rowView.findViewById(R.id.drawer_list_icon)).setImageResource(mImageIds[position]);
return rowView;
}
}
Some suggestions here.
1) Extend BaseAdapter instead of ArrayAdapter.
2) implement getCount method of base adapter and return list.size as return value(integer). here list can be your arrays length.