I want to create an expandable list view Keeping some child visible,where as I want to show rest on click.
Please suggest what is the best approach in such scenario,if any custom element or any tutorial as such.
Many Thanks,
This will be helpful to you.
Adapter class:-
public class MyExpandableAdapter extends BaseExpandableListAdapter {
private Activity activity;
private ArrayList<Object> childtems;
private LayoutInflater inflater;
private ArrayList<String> parentItems, child;
public MyExpandableAdapter(ArrayList<String> parents,
ArrayList<Object> childern) {
this.parentItems = parents;
this.childtems = childern;
}
public void setInflater(LayoutInflater inflater, Activity activity) {
this.inflater = inflater;
this.activity = activity;
}
#Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
child = (ArrayList<String>) childtems.get(groupPosition);
TextView textView = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.group, null);
}
textView = (TextView) convertView.findViewById(R.id.textView1);
textView.setText(child.get(childPosition));
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(activity, child.get(childPosition),
Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.row, null);
}
((CheckedTextView) convertView).setText(parentItems
.get(groupPosition));
((CheckedTextView) convertView).setChecked(isExpanded);
return convertView;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
#Override
public int getChildrenCount(int groupPosition) {
return ((ArrayList<String>) childtems.get(groupPosition)).size();
}
#Override
public Object getGroup(int groupPosition) {
return null;
}
#Override
public int getGroupCount() {
return parentItems.size();
}
#Override
public void onGroupCollapsed(int groupPosition) {
super.onGroupCollapsed(groupPosition);
}
#Override
public void onGroupExpanded(int groupPosition) {
super.onGroupExpanded(groupPosition);
}
#Override
public long getGroupId(int groupPosition) {
return 0;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
}
MainActivity is here.
public class MainActivity extends ExpandableListActivity {
private ArrayList<String> parentItems = new ArrayList<String>();
private ArrayList<Object> childItems = new ArrayList<Object>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// this is not really necessary as ExpandableListActivity contains
// an ExpandableList
// setContentView(R.layout.main);
ExpandableListView expandableList = getExpandableListView(); // you
// can
// use
// (ExpandableListView)
// findViewById(R.id.list)
expandableList.setDividerHeight(2);
expandableList.setGroupIndicator(null);
expandableList.setClickable(true);
setGroupParents();
setChildData();
MyExpandableAdapter adapter = new MyExpandableAdapter(parentItems,
childItems);
adapter.setInflater(
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE),
this);
expandableList.setAdapter(adapter);
expandableList.setOnChildClickListener(this);
}
public void setGroupParents() {
parentItems.add("Android");
parentItems.add("Core Java");
parentItems.add("Desktop Java");
parentItems.add("Enterprise Java");
}
public void setChildData() {
// Android
ArrayList<String> child = new ArrayList<String>();
child.add("Core");
child.add("Games");
childItems.add(child);
// Core Java
child = new ArrayList<String>();
child.add("Apache");
child.add("Applet");
child.add("AspectJ");
child.add("Beans");
child.add("Crypto");
childItems.add(child);
// Desktop Java
child = new ArrayList<String>();
child.add("Accessibility");
child.add("AWT");
child.add("ImageIO");
child.add("Print");
childItems.add(child);
// Enterprise Java
child = new ArrayList<String>();
child.add("EJB3");
child.add("GWT");
child.add("Hibernate");
child.add("JSP");
childItems.add(child);
}
}
At start open the groups you want to be fixed then implement this , specify the the groups postion
expandableList.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
if(groupPosition==your group position){
return true; // This way the expander cannot be collapsed
}else{
return false;
}
}
});
Override onGroupCollapsed and onGroupExpanded of the ExpandableListView based on your needs.
EDITED: In addition: implement the mentioned setOnGroupClickListener, store the groupIDs within your view, and suppress the collapsing in onGroupCollapsed.
Related
I have nested RecyclerView and two LiveData. one is parentList and another one is childList
I managed to use LiveData for ParentAdapter but when I try LiveData for ChildAdapter nothing showen in childAdapter. ParentAdapter is working.
Can someone help me?
Thanks?
this method is in MainActivity.class
private void sendAllDataToAdapter(){
CashFlowViewModel viewModel = ViewModelProviders.of(this).get(CashFlowViewModel.class);
viewModel.cashGroupByDate().observe(this, new Observer<List<CashFlow>>() {
#Override
public void onChanged(List<CashFlow> cashFlows) {
adapter.submitList(cashFlows);
}
});
adapter = new MainAdapter(this, this);
recyclerView.setAdapter(adapter);
}
This is ParentAdapter
public class MainAdapter extends ListAdapter<CashFlow, MainAdapter.MainViewHolder>{
Context context;
List<CashFlow> cashFlowList = new ArrayList<>();
List<CashFlow> cashFlowListChild = new ArrayList<>();
CashflowRepository repository;
CashFlowViewModel viewModel;
LifecycleOwner lifecycleOwner;
public MainAdapter(Context context, LifecycleOwner lifecycleOwner) {
super(diffCallback);
this.context = context;
this.cashFlowList = cashFlowList;
this.cashFlowListChild = cashFlowListChild;
this.repository = repository;
this.lifecycleOwner = lifecycleOwner;
viewModel = ViewModelProviders.of((MainActivity) context).get(CashFlowViewModel.class);
}
private static final DiffUtil.ItemCallback<CashFlow> diffCallback = new DiffUtil.ItemCallback<CashFlow>() {
#Override
public boolean areItemsTheSame(#NonNull CashFlow oldItem, #NonNull CashFlow newItem) {
return oldItem.getId() == newItem.getId();
}
#Override
public boolean areContentsTheSame(#NonNull CashFlow oldItem, #NonNull CashFlow newItem) {
return oldItem.getAdded_date().equals(newItem.getAdded_date())
&& oldItem.getTitle().equals(newItem.getTitle())
&& oldItem.getBody().equals(newItem.getBody());
}
};
#NonNull
#Override
public MainViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.main_adapter, parent, false);
return new MainViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MainViewHolder holder, int position) {
holder.tvDate.setText(getItem(position).getAdded_date());
holder.tvIncome.setText(String.valueOf(getItem(position).getIncome()));
holder.tvExpense.setText(String.valueOf(getItem(position).getExpense()));
ChildAdapter adapter = new ChildAdapter(context);
holder.rvChild.setAdapter(adapter);
viewModel.cashGroupByDate().observe(lifecycleOwner, new Observer<List<CashFlow>>() {
#Override
public void onChanged(List<CashFlow> cashFlows) {
adapter.submitList(cashFlows);
}
});
Log.d("Child", getItem(position).getAdded_date()+"");
}
public class MainViewHolder extends RecyclerView.ViewHolder {
TextView tvDate, tvIncome, tvExpense;
RecyclerView rvChild;
public MainViewHolder(#NonNull View itemView) {
super(itemView);
tvDate = itemView.findViewById(R.id.main_adapter_date);
tvIncome = itemView.findViewById(R.id.main_adapter_income);
tvExpense = itemView.findViewById(R.id.main_adapter_expense);
rvChild = itemView.findViewById(R.id.child_recyclerview);
}
}
This is ChildAdapter
public class ChildAdapter extends ListAdapter<CashFlow, ChildAdapter.ChildViewHolder> {
Context context;
public ChildAdapter(Context context) {
super(diffCallback);
this.context = context;
}
private static final DiffUtil.ItemCallback<CashFlow> diffCallback = new DiffUtil.ItemCallback<CashFlow>() {
#Override
public boolean areItemsTheSame(#NonNull CashFlow oldItem, #NonNull CashFlow newItem) {
return oldItem.getId() == newItem.getId();
}
#Override
public boolean areContentsTheSame(#NonNull CashFlow oldItem, #NonNull CashFlow newItem) {
return oldItem.getAdded_date().equals(newItem.getAdded_date())
&& oldItem.getBody().equals(newItem.getBody())
&& oldItem.getTitle().equals(newItem.getTitle())
&& oldItem.getExpense() == newItem.getExpense()
&& oldItem.getIncome() == newItem.getIncome()
&& oldItem.getType().equals(newItem.getType());
}
};
#NonNull
#Override
public ChildViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.child_adapter, parent, false);
return new ChildViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ChildViewHolder holder, int position) {
holder.imageView.setImageResource(getItem(position).getImage_id());
holder.tvTitle.setText(getItem(position).getTitle());
if (getItem(position).getType().equals(BaseActivity.INCOME)){
holder.tvSum.setText(String.valueOf(getItem(position).getIncome()));
}
else if (getItem(position).getType().equals(BaseActivity.EXPENSE)){
holder.tvSum.setText(String.valueOf(getItem(position).getExpense()));
}
}
public class ChildViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView tvTitle, tvSum;
public ChildViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.child_adapter_image);
tvTitle = itemView.findViewById(R.id.child_adapter_title);
tvSum = itemView.findViewById(R.id.child_adapter_sum);
}
}
}
This is my ViewModel.class
public class CashFlowViewModel extends AndroidViewModel {
private CashflowRepository repository;
public CashFlowViewModel(#NonNull Application application) {
super(application);
repository = new CashflowRepository(application);
}
public void insert(CashFlow cashFlow){
repository.insert(cashFlow);
}
public void update(CashFlow cashFlow){
repository.update(cashFlow);
}
public void delete(CashFlow cashFlow){
repository.delete(cashFlow);
}
public LiveData<List<CashFlow>> cashGroupByDate(){
return repository.getCashGroupByDate();
}
public LiveData<List<CashFlow>> cashByDate(String addedDate){
return repository.getCashByDate(addedDate);
}
public void insertCategory(Category category){
repository.insertCategory(category);
}
public void updateCategory(Category category){
repository.updateCategory(category);
}
public void deleteCategory(Category category){
repository.deleteCategory(category);
}
public List<Category> allCategories(String type){
return repository.getAllCategories(type);
}
My listview is found inside a ScrollView. The ListView was extended by ExpandableHeightListView class. When, 20 row items are loaded, the image library freeze the UI until all images are loaded. Then, user can scroll and select an item. To handle this issue, I tried to load every 10 records in the arraylist. Can i do it directly in the ExpandableHeightListView , if so how ?
public class ExpandableHeightListView extends ListView {
boolean expanded = false;
public ExpandableHeightListView(Context context) {
super(context);
}
public ExpandableHeightListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExpandableHeightListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public boolean isExpanded() {
return expanded;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isExpanded()) {
// int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Calculate entire height by providing a very large height hint.
// MEASURED_SIZE_MASK represents the largest height possible.
//int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);
//super.onMeasure(widthMeasureSpec, expandSpec);
// Calculate entire height by providing a very large height hint.
// But do not use the highest 2 bits of this integer; those are
// reserved for the MeasureSpec mode.
int expandSpec = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
}
The ListView adapter is as follows:
public class ResultatRechercheAdapter extends BaseAdapter {
public static final String IMAGE_CACHE_DIR = "images";
public static final String EXTRA_IMAGE = "extra_image";
public List<MRechercheResult> items;
public final OnClickListener itemButtonClickListener;
public final Context context;
public Activity activity;
public String agenda_date;
public String agenda_from;
public String agenda_to;
public ViewHolder holder;
public int agenda_from_hour=-1;
public int agenda_from_minute=-1;
public int agenda_to_hour;
public int agenda_to_minute;
public String from_am_pm;
public String to_am_pm;
private String monday;
private String tuesday;
private String wednesday;
private String thursday;
private String friday;
private String saturday;
private String sunday;
public ImageFetcher mImageFetcher;
public ResultatRechercheAdapter(Activity activity,Context context, List<MRechercheResult> resultat, OnClickListener itemButtonClickListener) {
this.activity = activity;
this.context = context;
this.items = resultat;
this.itemButtonClickListener = itemButtonClickListener;
//this.mImageFetcher = mImageFetcher;
try {
monday= activity.getResources().getString(R.string.monday);
tuesday= activity.getResources().getString(R.string.tuesday);
wednesday= activity.getResources().getString(R.string.wednesday);
thursday= activity.getResources().getString(R.string.thursday);
friday= activity.getResources().getString(R.string.friday);
saturday= activity.getResources().getString(R.string.saturday);
sunday= activity.getResources().getString(R.string.sunday);
} catch(Exception ex){}
}
#Override
public int getCount() {
return items.size();//items.size()
}
#Override
public MRechercheResult getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return 1;//items.size()
}
#Override
public int getItemViewType(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.list_item_card, null);
holder = new ViewHolder();
holder.txRowTitle = (TextView) convertView.findViewById(R.id.txRowTitle);
holder.imThumbnail= (RecyclingImageView) convertView.findViewById(R.id.imThumbnail);
holder.itemButton1 = (Button) convertView.findViewById(R.id.list_item_card_close);
holder.itemButton2 = (Button) convertView.findViewById(R.id.list_item_card_button_2);
holder.imCircleLundi= (ImageView) convertView.findViewById(R.id.imCircleLundi);
holder.imCircleMardi= (ImageView) convertView.findViewById(R.id.imCircleMardi);
holder.imCircleMercredi= (ImageView) convertView.findViewById(R.id.imCircleMercredi);
holder.imCircleJeudi= (ImageView) convertView.findViewById(R.id.imCircleJeudi);
holder.imCircleVendredi= (ImageView) convertView.findViewById(R.id.imCircleVendredi);
holder.imCircleSamedi= (ImageView) convertView.findViewById(R.id.imCircleSamedi);
holder.imCircleDimanche= (ImageView) convertView.findViewById(R.id.imCircleDimanche);
holder.rlListRecherche= (RelativeLayout) convertView.findViewById(R.id.rlListRecherche);
holder.llImage= (LinearLayout) convertView.findViewById(R.id.llImage);
holder.rlListClose= (RelativeLayout) convertView.findViewById(R.id.rlListClose);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
boolean no_record = items.get(position).no_record;
if (no_record){ // listview is empty
holder.llImage.setVisibility(View.GONE);
holder.rlListClose.setVisibility(View.GONE);
holder.rlListRecherche.setVisibility(View.VISIBLE);
} else {
Utils.shortWeek(activity, convertView);
holder.llImage.setVisibility(View.VISIBLE);
holder.rlListClose.setVisibility(View.VISIBLE);
holder.rlListRecherche.setVisibility(View.GONE);
if (itemButtonClickListener != null) {
//holder.itemButton1.setOnClickListener(itemButtonClickListener);
holder.itemButton1.setVisibility(View.GONE);
holder.itemButton2.setOnClickListener(itemButtonClickListener);
}
final String image_url = items.get(position).profil_photo.toString().replace("\\","").replace("hepigo", "helpigo");
String item_title = items.get(position).profil.toString();
if (item_title.equalsIgnoreCase("Julien Perez")){
if (true){
String display_pos = String.valueOf(position);
System.out.println(display_pos);
}
}
//searchRequest(position,image_url);
//if (!TextUtils.isEmpty(image_url))
// mImageFetcher.loadImage(image_url, holder.imThumbnail);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if (TextUtils.isEmpty(items.get(position).profil_photo)) {
//no url
} else {
Picasso.with(activity)
.load(image_url)
.error(android.R.drawable.stat_notify_error)
.transform(transformation)
.placeholder(R.drawable.loading_image_placeholder)
.config(Config.RGB_565)
.into(holder.imThumbnail);
}
}
});
//if (!TextUtils.isEmpty(image_url))
// new DownloadImageTask(holder.imThumbnail).execute(image_url);
holder.txRowTitle.setText(item_title);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
List<Agenda> agenda = items.get(position).agenda;
Utils.displayAgenda(agenda,holder.imCircleLundi,monday);
Utils.displayAgenda(agenda,holder.imCircleMardi,tuesday);
Utils.displayAgenda(agenda,holder.imCircleMercredi,wednesday);
Utils.displayAgenda(agenda,holder.imCircleJeudi,thursday);
Utils.displayAgenda(agenda,holder.imCircleVendredi,friday);
Utils.displayAgenda(agenda,holder.imCircleSamedi,saturday);
Utils.displayAgenda(agenda,holder.imCircleDimanche,sunday);
}
});
}
return convertView;
}
public static class ViewHolder {
public RelativeLayout rlListClose;
public LinearLayout llImage;
public RelativeLayout rlListRecherche;
public ImageView imCircleSamedi;
public ImageView imCircleDimanche;
public ImageView imCircleVendredi;
public ImageView imCircleJeudi;
public ImageView imCircleMercredi;
public ImageView imCircleMardi;
public ImageView imCircleLundi;
public RecyclingImageView imThumbnail;
public TextView txRowTitle;
public Button itemButton1;
public Button itemButton2;
}
I have an Activity with ViewPager which manage 2 Fragments using FragmentStatePagerAdapter,
The fragments have ListViews, each of the ListView shows data and I am able to go from Fragment_A to Fragment_B by swipe or item tapping on the ListView of Fragment_A.
I am also able to update the underlying data source for Fragment_B based on the item selected in Fragment_A. But when I try to notifyDataSetChanged() on the DataAdapter of Fragment_B, I am getting NullPointerException .
I want to update the data in Fragment_B according to the item selected in Fragment_A.
Here is my code
public class MyActivity extends FragmentActivity implements AdapterView.OnItemClickListener{
ViewPager viewPager = null;
int mSelectedItemPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_fail_activity);
viewPager = (ViewPager) findViewById(R.id.fail_pager_VP);
viewPager.setAdapter(new pagerAdapter(getSupportFragmentManager()));
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mSelectedItemPosition = position;
viewPager.setCurrentItem(1);
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter) viewPager.getAdapter();
Fragment_B item = (Fragment_B) fspa.getItem(1);
item.setData(position);
item.refresh();
}
}
class pagerAdapter extends FragmentStatePagerAdapter {
public pagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0) {
fragment = new Fragment_A();
} else if (position == 1) {
fragment = new Fragment_B();
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
String title = "";
if (position == 0) {
return "a_title";
}else if (position == 1) {
return "b_title";
}
}
}
public class Fragment_A extends android.support.v4.app.Fragment {
private ListView frag_a_listView;
DataAdapter dataAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView frag_a_listView = (ListView) getActivity().findViewById(R.id.frag_a_LV);
frag_a_listView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_fail_main, container, false);
frag_a_listView = (ListView) layout.findViewById(R.id.frag_a_LV);
dataAdapter = new DataAdapter(getActivity(),
R.layout.data_row,
R.id.data_label_TV,
getFrag_aData());
frag_a_listView.setAdapter(dataAdapter);
return layout;
}
private List<String> getFrag_aData() {
...
return someData;
}
}
public class Fragment_B extends android.support.v4.app.Fragment {
ListView frag_b_listView;
List<String> mData;
DataAdapter dataAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView frag_b_listView = (ListView) getActivity().findViewById(R.id.frag_b_LV);
frag_b_listView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_frag_b, container, false);
frag_b_listView = (ListView) layout.findViewById(R.id.frag_b_LV);
setData(0);
dataAdapter = new DataAdapter(getActivity(),
R.layout.data_row,
R.id.data_label_TV,
mData);
frag_b_listView.setAdapter(dataAdapter);
return layout;
}
public void setData(int position) {
...
mData = some List<String>;
}
public void refresh() {
dataAdapter.notifyDataSetChanged(); <------- this crashes the app
}
}
public class DataAdapter extends ArrayAdapter {
public DataAdapter(Context context, int resource, int textViewResourceId, List objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
return convertView;
}
}
here is the crash log
06-25 16:51:46.813 21537-21537/au.myCity.eight E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: au.myCity.eight, PID: 21537
java.lang.NullPointerException: Attempt to invoke virtual method 'void au.myCity.eight.dataAdapter.notifyDataSetChanged()' on a null object reference
at au.myCity.eight.fragments.Fragment_B.refresh(Fragment_B.java:56)
at au.myCity.eight.MyActivity.onItemClick(MyActivity.java:37)
at android.widget.AdapterView.performItemClick(AdapterView.java:305)
at android.widget.AbsListView.performItemClick(AbsListView.java:1146)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3053)
at android.widget.AbsListView$3.run(AbsListView.java:3860)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
After few tries with Log.d and checking some variable references.
The problem was the reference to Fragment_B changed by the time I called dataAdapter.notifyDataSetChanged(), to fix this I used the solution suggested in SO here, thanks to the "Streets Of Boston".
Summery, In the PagerAdapter:
Save a reference to initialized fragments in a SparseArray, use getRegisteredFragment in
onItemClick instead of getItem in MyActivity.
Override instantiateItem and destroyItem as suggested in the link.
private ArrayList<MFRList> list;
private ArrayList<STUList> list1 = new ArrayList<STUList>();
public ResultPage(PageParameters params) throws APIException {
Form form = new Form("form");
PageableListView view = new PageableListView("view", list, 10) {
#Override
public void onConfigure() {
super.onConfigure();
setVisible(list.size() > 0);
}
#Override
protected void populateItem(ListItem item) {
final StuList stu= (StuList) item.getModelObject();
item.add(new CheckBox("check", item.getModel()));
item.add(new Label("name", stu.getName()));
item.add(new Label("num", stu.getNumber()));
item.add(new Label("age", stu.getAge()));
item.add(new Label("sex", stu.getSex()));
}
};
Button backtosearchbutton = new Button("backtosearchbutton") {
#Override
public void onSubmit() {
setResponsePage(SearchPage.class);
}
}.setDefaultFormProcessing(false);
Button groupcheckbutton = new Button("groupcheckbutton") {
#Override
public void onSubmit() {
}
}.setDefaultFormProcessing(false);
Button groupuncheckbutton = new Button("groupuncheckbutton") {
#Override
public void onSubmit() {
}
}.setDefaultFormProcessing(false);
Button submitselectionbutton = new Button("submitselectionbutton") {
#Override
public void onSubmit() {
}
}.setDefaultFormProcessing(true);
form.add(view);
form.add(backtosearchbutton);
form.add(submitselectionbutton);
form.add(groupuncheckbutton);
form.add(groupcheckbutton);
add(form);
add(new CustomPagingNavigator("navigator", view));
how are the selected records stored and how can i use it. i understand that on form submission these records are submitted but i am not clear on how and where.
and my pojo is
public class MFRList implements Serializable {
private String name;
private String num;
private String age;
private String sex;
private Boolean selected = Boolean.FALSE;
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public String getnum() {
return num;
}
public void setnum(String num) {
this.num = num;
}
public String getAge() {
return age;
}
public void setsex(String sex) {
this.sex= sex;
}
public String getsex() {
return sex;
}
public void setage(String age) {
this.age = age;
}
public Boolean getSelected() {
return selected;
}
public void setSelected(Boolean selected) {
this.selected = selected;
}
}
where is the selected row saved and how can i retrieve and use it.
Thanks in Advance
You should use a CheckGroup with Checks instead:
public ResultPage(PageParameters params) throws APIException {
Form form = new Form("form");
CheckGroup selection = new CheckGroup("selection", new ArrayList());
selection.setRenderBodyOnly(false);
form.add(selection);
PageableListView view = new PageableListView("view", list, 10) {
#Override
public void onConfigure() {
super.onConfigure();
setVisible(list.size() > 0);
}
#Override
protected void populateItem(ListItem item) {
final StuList stu= (StuList) item.getModelObject();
item.add(new Check("check", item.getModel()));
item.add(new Label("name", stu.getName()));
item.add(new Label("num", stu.getNumber()));
item.add(new Label("age", stu.getAge()));
item.add(new Label("sex", stu.getSex()));
}
};
selection.add(view);
This way the arrayList passed to the CheckGroup constructor will always contain the selected objects.
I got what i was trying to acheive but i am not su7re if it is optimal solution.
I created my own Model and added the object to a list when check box is selected.
class SelectedCheckBoxModel extends AbstractCheckBoxModel {
private final STUList info;
private ArrayList<STUList> list1;
public SelectedCheckBoxModel(STUList info, ArrayList<STUList> list1) {
super();
this.info = info;
this.list1 = list1;
}
#Override
public boolean isSelected() {
// TODO Auto-generated method stub
return list1.contains(info);
}
#Override
public void select() {
// TODO Auto-generated method stub
list1.add(info);
}
#Override
public void unselect() {
// TODO Auto-generated method stub
list1.remove(info);
}
and i called it in my listview
check = new CheckBox("check", new SelectedCheckBoxModel(stu, list1));
item.add(check);
if this is not optimal please suggest
Thank You
I want to fire the "open root node" event on my current working CellTree, which now has the following behaviour:
#Override
public <T> NodeInfo<?> getNodeInfo(final T value) {
return new DefaultNodeInfo<Categoria>(
(value instanceof Categoria) ?
createBranchDataProvider((Categoria)value) :
rootDataProvider,
new CategoriaCell()
);
}
private AsyncDataProvider<Categoria> createRootDataProvider() {
AsyncDataProvider<Categoria> dataProvider = new AsyncDataProvider<Categoria>() {
#Override
protected void onRangeChanged(HasData<Categoria> display) {
AsyncCallback<Categoria[]> cb = new AsyncCallback<Categoria[]>() {
#Override
public void onSuccess(Categoria[] result) {
updateRowCount(result.length, true);
updateRowData(0, Arrays.asList(result));
}
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.toString());
}
};
rpcService.getCategorie(cb);
}
};
return dataProvider;
}
How can I fire that "onRangeChanged" event, to refresh my level-1 nodes?
What is my convenience method missing?
private void updateTree() {
TreeNode rootTreeNode = cellTree.getRootTreeNode();
for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
rootTreeNode.setChildOpen(i, false);
}
// HOW TO REFRESH LEVEL-1 NODES?
}
Working example. Add reference to DataProvider (and parent Node) (MyMenuItem and MyCell with DataProvider in my code). After adding element refresh parent.
public class MyMenuItem {
private String name;
private String action; //some data
private int level; //if needed
private ArrayList<MyMenuItem> list; //nodes childrens
private MyMenuItem parent; //track internal parent
private MyCell cell; //for refresh - reference to visual component
public void setCell(MyCell cell) {
this.cell = cell;
}
public void refresh() {
if(parent!=null) {
parent.refresh();
}
if (cell!=null) {
cell.refresh(); //refresh tree
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public MyMenuItem(String name, String action) {
super();
parent = null;
level = 0;
this.name = name;
this.action = action;
list = new ArrayList<MyMenuItem>();
}
public MyMenuItem(String name) {
this(name, "");
}
public void addSubMenu(MyMenuItem m) {
m.level = this.level+1;
m.parent = this;
list.add(m);
}
public boolean hasChildrens() {
return list.size()>0;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public ArrayList<MyMenuItem> getList() {
return list;
}
public MyMenuItem getParent() {
return parent;
}
}
public class MyTreeModel implements TreeViewModel {
private MyMenuItem officialRoot; //default not dynamic
private MyMenuItem studentRoot; //default not dynamic
private MyMenuItem testRoot; //default not dynamic
private MyMenuItem root;
public MyMenuItem getRoot() { // to set CellTree root
return root;
}
public MyTreeModel() {
root = new MyMenuItem("root");
// Default items
officialRoot = new MyMenuItem("Official"); //some basic static data
studentRoot = new MyMenuItem("Student");
testRoot = new MyMenuItem("Test");
root.addSubMenu(officialRoot);
root.addSubMenu(studentRoot);
root.addSubMenu(testRoot);
}
//example of add add logic
private void addNew(MyMenuItem myparent, String name, String uid) {
myparent.addSubMenu(new MyMenuItem(name, uid));
myparent.refresh(); //HERE refresh tree
}
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
ListDataProvider<MyMenuItem> dataProvider;
MyMenuItem myValue = null;
if (value == null) { // root is not set
dataProvider = new ListDataProvider<MyMenuItem>(root.getList());
} else {
myValue = (MyMenuItem) value;
dataProvider = new ListDataProvider<MyMenuItem>(myValue.getList());
}
MyCell cell = new MyCell(dataProvider); //HERE Add reference
if (myValue != null)
myValue.setCell(cell);
return new DefaultNodeInfo<MyMenuItem>(dataProvider, cell);
}
#Override
public boolean isLeaf(Object value) {
if (value instanceof MyMenuItem) {
MyMenuItem t = (MyMenuItem) value;
if (!t.hasChildrens())
return true;
return false;
}
return false;
}
}
public class MyCell extends AbstractCell<MyMenuItem> {
ListDataProvider<MyMenuItem> dataProvider; //for refresh
public MyCell(ListDataProvider<MyMenuItem> dataProvider) {
super("keydown","dblclick");
this.dataProvider = dataProvider;
}
public void refresh() {
dataProvider.refresh();
}
#Override
public void onBrowserEvent(Context context, Element parent, MyMenuItem value,
NativeEvent event, ValueUpdater<MyMenuItem> valueUpdater) {
if (value == null) {
return;
}
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
this.onEnterKeyDown(context, parent, value, event, valueUpdater);
}
if ("dblclick".equals(event.getType())) {
this.onEnterKeyDown(context, parent, value, event, valueUpdater);
}
}
#Override
public void render(Context context, MyMenuItem value, SafeHtmlBuilder sb) {
if (value == null) {
return;
}
sb.appendEscaped(value.getName());
//add HERE for better formating
}
#Override
protected void onEnterKeyDown(Context context, Element parent,
MyMenuItem value, NativeEvent event, ValueUpdater<MyMenuItem> valueUpdater) {
Window.alert("You clicked "+event.getType()+" " + value.getName());
}
}
in module add
treeModel = new MyTreeModel();
tree = new CellTree(treeModel,treeModel.getRoot());
The Level-1 nodes (I suppose you the mean below the root node) can not be refreshed the way you are doing it.
You have to store the instance of your dataProvider for the level-1 nodes somewhere.
Later when you refresh your list you have to update your stored dataProvider for your level-1 nodes.
The nodes below the level-1 can be refreshed the way you are doing it. Because as soon as you close the level 1 nodes (that is what you are doing in the updateTree method) and the next time you open it getNodeInfo will be called and the updated Subcategories will be retrieved and displayed in the CellTree.
UPDATE
For refreshing the CellWidgets which is attached to AsyncDataProvider you will probably have to extend the AsyncDataProvider and either extract the RPC call to a getData() method which is called in the onRangeChanged() method or create an interface with a refresh method and implement it in your custom AsyncDataProvider which calls the protected onRangeChanged() method.