How to get access to item (object) in a ViewPager? - java

I've created an acitvity that must have two pages. Those two pages shouldn't work like two different and unrelated activities, but like, let's say, one activity with two work area. Switching between them just with sliding right or left.
So I've impleneted it and switching works, but I can't get access to the object inside ViewPager.
Description:
Parent activity activity_setdetail.xml has two area: list view_setdetail_1.xml - of items and view_setdetail_2.xml - some settings. So, those two areas relate to different *.xml.
XMLs
activity_setdetail.xml
<android.support.v4.view.ViewPager
android:id="#+id/vpager"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="2dp"
android:layout_marginEnd="2dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginStart="2dp"
android:layout_marginTop="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
view_setdetail_1.xml it goes to ViewPager vpager as right side area
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/listViewOfWords"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="2dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginStart="2dp"
android:layout_marginTop="8dp"
android:clickable="true"
android:focusable="true"
android:paddingBottom="20dp"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="#+id/txtToLBL"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtToLBL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="#string/view_goToSettings"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
view_setdetail_2.xml it goes to ViewPager vpager as left side area
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/txtCardsQTYinLessonlbl"
android:layout_width="0dp"
android:layout_height="38dp"
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:layout_marginTop="2dp"
android:gravity="center_vertical"
android:text="#string/txtCardsQTYinLessonLBLString"
android:textAlignment="center"
android:textColor="?attr/editTextColor"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/etxtCardsQTYinLesson"
android:layout_width="34dp"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginStart="2dp"
android:layout_marginTop="2dp"
android:ems="10"
android:imeOptions="actionDone"
android:inputType="number"
android:text="99"
android:textAlignment="center"
android:textSize="14sp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="#+id/txtCardsQTYinLessonlbl"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtTolistLBL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="#string/view_goToList"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
Resource file that enumerate screens for activity_setdetail.xml
public enum ResourcesModel {
FIRST_SCREEN(R.string.view_setdetail_1, R.layout.view_setdetail_1), SECOND_SCREEN(R.string.view_setdetail_2, R.layout.view_setdetail_2);
private int mTitleResourceId;
private int mLayoutResourceId;
ResourcesModel(int titleResId, int layoutResId) {
mTitleResourceId = titleResId;
mLayoutResourceId = layoutResId;
}
public int getTitleResourceId() {
return mTitleResourceId;
}
public int getLayoutResourceId() {
return mLayoutResourceId;
}
}
Adapter:
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import am.slotvin.hoodiesoft.by.enums.ResourcesModel;
public class SimplePagerAdapter extends PagerAdapter {
private Context mContext;
public SimplePagerAdapter(Context context) {
mContext = context;
}
#Override
public Object instantiateItem(ViewGroup viewGroup, int position) {
ResourcesModel resources = ResourcesModel.values()[position];
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(
resources.getLayoutResourceId(), viewGroup, false);
viewGroup.addView(layout);
return layout;
}
#Override
public void destroyItem(ViewGroup viewGroup, int position, Object view) {
viewGroup.removeView((View) view);
}
#Override
public int getCount() {
return ResourcesModel.values().length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public CharSequence getPageTitle(int position) {
ResourcesModel customPagerEnum = ResourcesModel.values()[position];
System.out.println("SimplePagerAdapter CharSequence getPageTitle" + position);
return mContext.getString(customPagerEnum.getTitleResourceId());
}
}
Java class for activity_setdetail.xml. I've reduced code just to only textview. But in reality I have ListView there and other stuff. Nevertheless, I can't influence even to textview.
public class SetDetail extends AppCompatActivity {
private String setName;
private int setID;
TextView txtToLBL;
SimplePagerAdapter spa;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setName = getIntent().getStringExtra("setName");
setID = getIntent().getIntExtra("setID", 0);
setTitle(this.getString(R.string.activity_setdetailLabel) + setName);
setContentView(R.layout.activity_setdetail);
spa = new SimplePagerAdapter(this);
ViewPager viewPager = (ViewPager) findViewById(R.id.vpager);
if (viewPager != null) {
viewPager.setAdapter(spa);
}
txtToLBL = (TextView) findViewById(R.id.txtToLBL); //doesn't work
//txtToLBL.setText("bla-bla-bla"); //error - android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
LayoutInflater inflater = LayoutInflater.from(this);
View v = inflater.inflate(R.layout.view_setdetail_1, null, false);
txtToLBL = (TextView) v.findViewById(R.id.txtToLBL);
txtToLBL.setText("bla-bla-bla");//also doesn't work. No errors, just no changes.
}
}
So the question is - How to gegt access to elements on views that loaded in a ViewPager?
I found similar questions, but they didn't work for me.
UPDATE 1:
So, I've completely moved all code (also a bunch of listeners) to my SimplePagerAdapter. Now it should be renamed, because it is not universal anylonger and closely-coupled with the java class of parent activity. Looks not very good, but the only way I found at the moment. Though works OK, without freezing. Still be good to hear more elegant solution.

A ViewPager inflates 3 fragments at a time, the current fragment in view and a fragment on both left and right side of it. Since, your ViewPager has only two fragments both are inflated. So you can use something like viewPager.findViewById(resId) where resId is the Id of the view you want to access

I have the same kind of issue, the viewPager and the PagerAdapter should have been designed with a callback for when it's finished loading it's views. If I put code I want to run inside onPageSelected it all works, its just not available onCreate or onResume (presumably because the view is not instantiated by the pager yet.. If I had hair I'd be pulling it out trying to set default text on TextViews when my activity is Created...

Related

Why my page is lagging while click on "Daily Meal"

I am working on food delivery application. I have four tab in menu bar Home, Daily Meal, Favourite and My Cart. My all tab is work well but when I click on Daily Meal my page is rendering. What can I try next?
Here is my code:
daily_meal_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.DailyMeal.DailyMealFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/daily_meal_rec"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
daily_meal_ver.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp">
<ImageView
android:id="#+id/imgview"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:src="#drawable/breakfast"
android:foreground="#drawable/blur"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/names"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/amita_bold"
android:text="Dinner"
android:textColor="#color/white"
android:textSize="40sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/imgview"
app:layout_constraintEnd_toEndOf="#+id/imgview"
app:layout_constraintStart_toStartOf="#+id/imgview"
app:layout_constraintTop_toTopOf="#+id/imgview"
app:layout_constraintVertical_bias="0.3" />
<TextView
android:id="#+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/amita"
android:text="Choose your best dinner"
android:textColor="#color/white"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/names" />
<TextView
android:id="#+id/discounts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/off_back"
android:padding="2sp"
android:text=" 20% OFF "
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/imgview"
app:layout_constraintStart_toStartOf="#+id/imgview"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.821" />
</androidx.constraintlayout.widget.ConstraintLayout>
DailyMealModel.java
public class DailyMealModel {
int image;
String name;
String discount;
String description;
// getter setter and constructor
}
DailyMealFragment.java
public class DailyMealFragment extends Fragment {
RecyclerView recyclerView;
List<DailyMealModel> dailyMealModels;
DailyMealAdapter dailyMealAdapter;
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.daily_meal_fragment,container,false);
recyclerView = root.findViewById(R.id.daily_meal_rec);
dailyMealModels = new ArrayList<>();
dailyMealModels.add(new DailyMealModel(R.drawable.breakfast,"Breakfast","30% OFF","Description Description"));
dailyMealModels.add(new DailyMealModel(R.drawable.lunch,"Lunch","15% OFF","Description Description"));
dailyMealAdapter = new DailyMealAdapter(getContext(),dailyMealModels);
recyclerView.setAdapter(dailyMealAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
return root;
}
}
DailyMealAdapter.java
public class DailyMealAdapter extends RecyclerView.Adapter<DailyMealAdapter.viewholder> {
Context context;
List<DailyMealModel> list;
public DailyMealAdapter(Context context, List<DailyMealModel> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.daily_meal_ver,parent,false));
}
#Override
public void onBindViewHolder(#NonNull viewholder holder, int position) {
holder.img.setImageResource(list.get(position).getImage());
holder.name.setText(list.get(position).getName());
holder.discount.setText(list.get(position).getDiscount());
holder.description.setText(list.get(position).getDescription());
}
#Override
public int getItemCount() {
return list.size();
}
public class viewholder extends RecyclerView.ViewHolder {
ImageView img;
TextView name,discount,description;
public viewholder(#NonNull View itemView) {
super(itemView);
img = itemView.findViewById(R.id.imgview);
name = itemView.findViewById(R.id.names);
description = itemView.findViewById(R.id.desc);
discount = itemView.findViewById(R.id.discounts);
}
}
}
Snapshot
As your attached screenshot,
please make sure all images and icons used in the app are lower sizes even loading dynamic images for that you can use tinypng.com or tinyjpg.com
also, using pagination in RecyclerView will improve your app performance.
and make sure JSON/XML list response is minimal.

Issue using 2 different recyclerView in 2 activities with 1 room database

Good day - I'm new to recyclerViews and connecting to Room database. I've got one working with the help from a tutorial and now I want to add to it. My aim is to:
Implement a Room database which in turn presents data to the user via a recyclerView.
Have 1 recyclerView in the main activity and a 2nd recyclerView in a second activity. I'm trying to have a different layout in each activity as shown in the following links.
Main activity:
Second activity:
The issue I'm having is even though the XML files are unique for each activity, along with the variables within, the name of the recyclerView, and also the methods for each activity, the layout in the second activity shows in the first activity.
activity_main has the following:
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="100dp"
android:id="#+id/recycler_view111"
android:layout_width="match_parent"
android:layout_height="114dp"
tools:listitem="#layout/testing" />
The second activity XML file has the following:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="488dp"
tools:listitem="#layout/testing1_item" />
Can someone please help me identify why the same recyclerView is shown across the 2 activities please?
To trouble-shoot, I've:
Gone through all the XML files to ensure there is no issue with the names of the files/methods etc.
Copied the layout from the activity_main xml and applied it to the second xml file. This then in turn displayed the layout that I'm testing within in MainActivity across both activities.
MainActivity uses the activity_main.xml which uses a test file called testing.xml - code as follows:
MainActivity:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(getApplicationContext(), AllWordsActivity.class);
startActivity(intent);
}
});
RecyclerView recyclerView111 = findViewById(R.id.recycler_view111);
recyclerView111.setLayoutManager(new LinearLayoutManager(this));
recyclerView111.setHasFixedSize(true);
NoteAdapter adapter = new NoteAdapter();
recyclerView111.setAdapter(adapter);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>()
{
#Override
public void onChanged(List<Note> notes)
{
adapter.setNotes(notes);
}
});
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginTop="500dp"
android:layout_marginRight="50dp"
android:background="#color/cardview_shadow_start_color"
android:maxLines="1"
android:text="Open new Activity!"
android:textColor="#color/black"
android:textSize="20dp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="100dp"
android:id="#+id/recycler_view111"
android:layout_width="match_parent"
android:layout_height="114dp"
tools:listitem="#layout/testing" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
testing.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/text_view_priority1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:textColorHighlight="#color/black"
android:text="1"
android:textAppearance="#style/TextAppearance.AppCompat.Large" />
<TextView
android:id="#+id/text_view_title1"
android:layout_width="323dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginStart="183dp"
android:layout_toStartOf="#id/text_view_priority1"
android:ellipsize="end"
android:maxLines="1"
android:text="Title1"
android:textAppearance="#style/TextAppearance.AppCompat.Large" />
<TextView
android:id="#+id/text_view_description1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="#id/text_view_title1"
android:text="Description1" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
The second activity is based on a class called AllWordsActivity" which uses activity_all_words which uses note_item test - code as follows:
AllWordsActivity.java
private NoteViewModel noteViewModel;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_words);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
NoteAdapter adapter = new NoteAdapter();
recyclerView.setAdapter(adapter);
//noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>()
{
#Override
public void onChanged(List<Note> notes)
{
adapter.setNotes(notes);
}
});
activity_all_words.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AllWordsActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="488dp"
tools:listitem="#layout/note_item" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
note_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/text_view_priority"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:textColor="#color/purple_500"
android:text="1"
android:textAppearance="#style/TextAppearance.AppCompat.Large"/>
<TextView
android:id="#+id/text_view_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Title"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:maxLines="1"
android:layout_toStartOf="#id/text_view_priority"
android:layout_alignParentStart="true"
android:ellipsize="end"/>
<TextView
android:id="#+id/text_view_description"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_below="#id/text_view_title"
android:text="Description" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
Code for noteAdapter:
```public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder>
{
private List notes = new ArrayList<>();
#NonNull
#Override
public NoteHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.note_item, parent, false);
return new NoteHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull NoteHolder holder, int position)
{
Note currentNote = notes.get(position);
holder.textViewTitle.setText(currentNote.getTitle());
holder.textViewDescription.setText(currentNote.getDescription());
holder.textViewPriority.setText(String.valueOf(currentNote.getPriority()));
}
#Override
public int getItemCount()
{
return notes.size();
}
public void setNotes(List<Note> notes)
{
this.notes = notes;
notifyDataSetChanged();
}```
The problem is that both activities use the same adapter for their list view: NoteAdapter adapter = new NoteAdapter();. In turn, NoteAdapter only inflates note_item.xml for each item in the list:
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.note_item, parent, false);
To fix this, you need to either change NoteAdapter to work with multiple layout files for its rows. Or you need to create a different adapter for each RecyclerView.
Original Answer:
It sounds like you are seeing the same items displaying in both of your recycler views. The problem is that both the MainActivity and the AllWordsActivity have these lines:
NoteAdapter adapter = new NoteAdapter();
recyclerView.setAdapter(adapter);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>()
{
#Override
public void onChanged(List<Note> notes)
{
adapter.setNotes(notes);
}
});
So both activities are getting data from the same ViewModel to display. To display different data, use a different ViewModel in the MainActivity.
p.s. I suggest using consistent naming. You have AllWordsActivity and NotesAdapater. Either use AllWords or Notes, but don't mix and match.

ExpandableListView shows only one groupView and no childView

I'm a newbie in Android. I want to show my records in a database using an expandable list view, so that records of the same day form a group. I want something like this:
day 1
-------------------
record 1 of day 1
record 2 of day 1
day 2
-------------------
record 1 of day 2
record 2 of day 2
record 3 of day 2
...
But what I get is this:
day 1
-------------------
Only one record is showing as the group view, and when I expand it, nothing shows as a child.
FirstFragment.java:
public class FirstFragment extends Fragment {
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
createExpandableListView();
}
private void createExpandableListView() {
String time = Long.toString(((ShowBillBookActivity)getActivity()).book.getTime().getTimeInMillis());
BillTableHandler handler = new BillTableHandler(getActivity(),
((MyApplication) getActivity().getApplication()).BILL_TABLE_NAME_PREFIX + time);
ExpandableListView view = (ExpandableListView) getView().findViewById(R.id.expandableListView);
Cursor c = handler.getAllBills();
Log.d("tag", "handler.getAllbills(): "+c.getCount());
ExpandableListAdapter adapter = new ExpandableListAdapter(handler,
this.getActivity(),
handler.getAllBills(),
R.layout.group_expandable_list_view,
new String[]{BillEntry.DAY, BillEntry.AMOUNT},
new int[]{R.id.textview_time, R.id.textview_extra},
R.layout.child_expandable_list_view,
new String[]{BillEntry.PAYER, BillEntry.AMOUNT},
new int[]{R.id.textview_payer, R.id.textview_amount});
view.setAdapter(adapter);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
}
ExpandableListAdapter.java
public class ExpandableListAdapter extends SimpleCursorTreeAdapter {
BillTableHandler handler;
public ExpandableListAdapter(BillTableHandler handler, Context context, Cursor cursor, int groupLayout,
String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom,
int[] childTo){
super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
this.handler = handler;
}
#Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
long time = groupCursor.getLong(groupCursor.getColumnIndexOrThrow(BillTableHandler.BillEntry.DAY));
Cursor c = handler.getBillsOfTime(time);
Log.d("tag","child Count : "+c.getCount());
c.moveToFirst();
return c;
}
}
group_expandable_list_view.xml
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textview_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textview_extra"
android:layout_width="61dp"
android:layout_height="18dp"
android:text="TextView"
app:layout_constraintLeft_toRightOf="#+id/textview_time"
android:layout_marginLeft="32dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp" />
</android.support.constraint.ConstraintLayout>
child_expandable_list_view.xml
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:focusable="false"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textview_payer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="hello"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textview_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:text="world"
app:layout_constraintLeft_toRightOf="#+id/textview_payer"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="text"
app:layout_constraintTop_toBottomOf="#+id/textview_amount"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent" />
</android.support.constraint.ConstraintLayout>
I've been working on this for about a week and am getting pretty desperate. So please, any suggestion is welcome.
It's working now. The reason is that in the fragment layout, the ExpandableListView is nested in a ScrollView. Apparently, this is not good practice, because the size of ExpandableListView could not be correctly calculated (for more explanations see this blog, unfortunately partly in Chinese). This way, you'll find that getChildView() of the base SimpleCursorTreeAdapter never gets called. That's why the child view never gets rendered.
Solution:
Get rid of ScrollView, just ExpandableListView will work fine. Or
Extend ExpandableListView as this answer does, if you have to have it nested under ScrollView.

Add ImageButton to ListView

Im trying to add an ImageButton to each row in my ListView (which I implemented via CustomAdapter). Each button should open a different WebView. I can't seem to find any tutorials to do this so any advice/tips/links would be highly apreciated.
EDIT 1:
My Listview XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_x="15dp">
<ImageView
android:layout_width="30dp"
app:srcCompat="#drawable/a"
android:layout_marginLeft="12dp"
android:layout_marginStart="12dp"
android:id="#+id/local"
android:layout_height="30dp"
android:layout_alignBottom="#+id/versus"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/resultsiz"
android:textColor="#android:color/white"
android:textStyle="normal|bold"
android:gravity="center_vertical"
android:elevation="15dp"
android:layout_alignBaseline="#+id/resultsde"
android:layout_alignBottom="#+id/resultsde"
android:layout_alignRight="#+id/resultsde"
android:layout_alignEnd="#+id/resultsde"
android:layout_marginRight="61dp"
android:layout_marginEnd="61dp" />
<ImageView
android:layout_width="15dp"
app:srcCompat="#drawable/a"
android:id="#+id/versus"
android:layout_height="15dp"
android:layout_marginLeft="31dp"
android:layout_marginStart="31dp"
android:layout_alignBottom="#+id/visit"
android:layout_toRightOf="#+id/local"
android:layout_toEndOf="#+id/local" />
<ImageView
android:layout_width="30dp"
app:srcCompat="#drawable/a"
android:id="#+id/visit"
android:layout_height="30dp"
android:layout_marginLeft="19dp"
android:layout_marginStart="19dp"
android:layout_alignBottom="#+id/resultsiz"
android:layout_toRightOf="#+id/versus"
android:layout_toEndOf="#+id/versus" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignLeft="#+id/local"
android:layout_alignStart="#+id/local"
android:id="#+id/dia"
android:textColor="#color/white"
android:textStyle="normal|bold"
android:textAllCaps="true" />
<TextView
android:text="TextView"
android:layout_height="wrap_content"
android:id="#+id/resultsde"
android:layout_marginRight="24dp"
android:layout_marginEnd="24dp"
android:textColor="#android:color/white"
android:layout_marginTop="19dp"
android:textStyle="normal|bold"
android:textAlignment="viewEnd"
android:gravity="end"
android:layout_width="70dp"
android:layout_below="#+id/dia"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/local"
android:layout_toRightOf="#+id/local"
android:layout_toEndOf="#+id/local"
android:layout_marginTop="155dp"
android:id="#+id/stats" />
</RelativeLayout>
And my CustomAdapter:
protected void onPostExecute(Void aVoid) {
CustomAdapter customAdapter = new CustomAdapter();
lista.setAdapter(customAdapter);
}
class CustomAdapter extends BaseAdapter{
#Override
public int getCount() {
return resultsizq.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
view = getLayoutInflater().inflate(R.layout.customlayout,null);
ImageView versus = (ImageView)view.findViewById(R.id.versus);
ImageView local = (ImageView)view.findViewById(R.id.local);
ImageView visit = (ImageView)view.findViewById(R.id.visit);
TextView dia= (TextView)view.findViewById(R.id.dia);
TextView resultsiz= (TextView)view.findViewById(R.id.resultsiz);
TextView resultsde= (TextView)view.findViewById(R.id.resultsde);
dia.setText(di[position]);
resultsiz.setText(resultsizq[position]);
resultsde.setText(resultsder[position]);
versus.setImageResource(versu[position]);
local.setImageResource(loc[position]);
visit.setImageResource(vis[position]);
if ((position+1)%4==0){
view.setPadding(0,0,0,150);
}
if ((position)%4==0){
view.setPadding(0,150,0,0);
}
return view;
}}
In the getView method, you should assign the onClick function to the Button according to the given position. Probably, you should get the item located at position, generate some url based on the properties of this item, and let this url be opened in the onClick function.
More than that, I have 3 suggestions to improve your code:
Try to use RecyclerView instead of ListView.
Even if you use ListView, have a look at View Holder pattern. This is a good place to start.
Consider using Butterknife, which increases the readability of your code. If I were you, I would keep the item as a property in the view holder object, which has a function annotated with #OnClick(R.id.stats) so that it opens the preferred WebView accordingly.
I hope these help.

ListView Elements Not Displaying

ListView elements are not displaying even though I've used almost identical code before. Sorry that I have to ask this type of question, but I seriously just don't understand why it's not working. None of the other similar questions I looked at were useful.
The heights of the items and ListView should be fine. Not sure what's going on. Thanks guys.
Here's the code dump:
Main Acitivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_city);
findViewById(R.id.loadingPanel).setVisibility(View.GONE); // remove loading animation
ArrayList<String> citiesList = new ArrayList<>();
citiesList.add("Waterloo");
citiesList.add("Guelph");
populateCities(citiesList);
}
public void populateCities(ArrayList<String> citiesList) {
// see what the list is
Toast.makeText(getApplicationContext(),citiesList.toString(),Toast.LENGTH_LONG).show();
// populate the ListView
CitiesListAdapter citiesListAdapter = new CitiesListAdapter(this, citiesList);
ListView citiesListView = (ListView)findViewById(R.id.cities_list);
citiesListView.setAdapter(citiesListAdapter);
// listen for when a city in the list is clicked
citiesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// go to the bar list activity (send the city and province with it)
TextView lblCity = (TextView)view.findViewById(R.id.lblCity);
String city = lblCity.getText().toString();
Toast.makeText(getApplicationContext(), city, Toast.LENGTH_LONG).show();
}
});
}
Here's the list adapter code (CitiesListAdapter):
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class CitiesListAdapter extends ArrayAdapter<String> {
private final Activity context;
private final ArrayList<String> cities;
public CitiesListAdapter(Activity context, ArrayList<String> cities) {
super(context, R.layout.cityitem);
this.context = context;
this.cities = cities;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.cityitem, null, true);
TextView lblCity = (TextView)rowView.findViewById(R.id.lblCity);
lblCity.setText(this.cities.get(position));
return rowView;
}
}
Then here's the main layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.myapp.SelectCity">
<RelativeLayout
android:id="#+id/loadingPanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:id="#+id/progressBar" />
</RelativeLayout>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btnBack"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:onClick="back"
android:src="#mipmap/ic_menu_back"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btnRefresh"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:onClick="refresh"
android:src="#mipmap/ic_action_refresh"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Select City"
android:id="#+id/lblTitle"
android:layout_below="#+id/btnBack"
android:layout_centerHorizontal="true" />
<RelativeLayout
android:id="#+id/listViewLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/lblTitle"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:layout_marginTop="20dp">
<ListView
android:background="#F00"
android:id="#+id/cities_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button"
android:layout_below="#+id/listViewLayout"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Then the ListView item layout (cityitem.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="City"
android:id="#+id/lblCity" />
</LinearLayout>
Edit: Looks like I'm also getting this stupid error that Android can't seem to fix (just sneaks in the LogCat):
E/Surface: getSlotFromBufferLocked: unknown buffer: 0xab7ccc40
Not sure if that's why nothing is displaying.
Screenshot: http://prntscr.com/avpy9s
The super call in your constructor doesn't include the ArrayList, nor are you overriding getCount() to return the list size, so your Adapter is returning 0 for the item count, and the ListView won't try to retrieve any Views. You could include the ArrayList in the super call, or override the getCount() method to return cities.size().
However, you don't necessarily need a custom Adapter for a simple ArrayList of Strings. You could simply use the constructor for ArrayAdapter that takes a layout and a TextView resource ID.
ArrayAdapter<String> citiesListAdapter = new ArrayAdapter<>(this,
R.layout.cityitem,
R.id.lblCity,
cities);
There's no layout in the ListView. You need to add layout(Linear or Relative) inside the ListView. Like this!
<ListView
<RelativeLayout />
/>
In the layout, you declare what you wanna show - TextView or ImageView or etc.

Categories

Resources