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.
Related
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.
I have a big SQLite database (7000+ items) with 16 columns per row. I would like to populate my custom recycler view, that I already made, with items from the database to make a huge recycler view list.
My question is this: How would you go about iterating through 2 entire columns of all of the rows. I need to fetch a name and an ID of each and every single item in the database and assign those values to 2 text views, that I created through a custom recycler view adapter. I already have a method in the database that returns a number of total rows (aka items) in a database. I would like to make a loop with i < getDbSize(); but I don't have a clear idea on how I would go about on incrementing through 2 particular columns of all rows and then applying that information onto a card in the recycler view.
Here is the xml code where recycler view sits:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CollegeFragment"
android:background="#color/colorPrimaryDark">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="College Search Tool"
android:textSize="28sp"
android:padding="10dp"
android:textColor="#color/colorWhite"
android:fontFamily="sans-serif-medium"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/grad_bg"
android:paddingBottom="10dp"
android:paddingRight="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ipeds id:"
android:textSize="24sp"
android:padding="10dp"
android:textColor="#color/colorWhite"
android:fontFamily="sans-serif-medium"/>
<EditText
android:id="#+id/et_ipeds"
android:layout_width="match_parent"
android:layout_height="40dp"
android:textColor="#color/colorWhite"
android:fontFamily="sans-serif-medium"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:background="#drawable/et_alt1_bg"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name: "
android:textSize="24sp"
android:padding="10dp"
android:textColor="#color/colorWhite"
android:fontFamily="sans-serif-medium"/>
<EditText
android:id="#+id/et_name"
android:layout_width="match_parent"
android:layout_height="40dp"
android:textColor="#color/colorWhite"
android:fontFamily="sans-serif-medium"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:background="#drawable/et_alt1_bg"/>
</LinearLayout>
</LinearLayout>
<TextView
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RESULT"
android:textSize="28sp"
android:padding="10dp"
android:textColor="#color/colorWhite"
android:fontFamily="sans-serif-medium"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"/>
</LinearLayout>
</FrameLayout>
and Java:
public class CollegeFragment extends Fragment implements ItemClickListener{
private RecyclerView recyclerView;
private CustomRecyclerAdapter customRecyclerAdapter;
private List<CollegeItem> collegeItemList = new ArrayList<>();
private DatabaseCollege dbCollege;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View myFragmentView = inflater.inflate(R.layout.fragment_college, container, false);
dbCollege = new DatabaseCollege(getActivity());
recyclerView = myFragmentView.findViewById(R.id.recycler);
customRecyclerAdapter = new CustomRecyclerAdapter(collegeItemList, getActivity());
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(customRecyclerAdapter);
customRecyclerAdapter.setItemClickListener(this);
//populate collegeItemList with dummy values for testing
String name = "College 1";
String id = "12345647653";
String name2 = "College 2";
String id2 = "12345";
CollegeItem college = new CollegeItem(name, id);
CollegeItem college2 = new CollegeItem(name2, id2);
collegeItemList.add(college);
collegeItemList.add(college2);
return myFragmentView;
}
#Override
public void onClick(View v, int position) {
String name = collegeItemList.get(position).getName();
String id = collegeItemList.get(position).getId();
}
public void populateList() {
int numOfColleges = dbCollege.getNumOfColleges();
for(int i = 0; i < numOfColleges; i++) {
//read in data from database into collegeItemList recyclerView here
}
}
}
I also included a picture with what I am trying to achieve that contains manually inserted variables. I basically want to populate that list with cards that each contain info(ID and name) about each and every item from database.
You need to query the database first to get those two fields like below:
ArrayList<CollegeItem> arr = new ArrayList<>();
String selectQuery = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Move to first row
cursor.moveToFirst();
while (cursor.isAfterLast() == false)
{
arr.add(new CollegeItem(cursor.getString(1),
cursor.getString(2));
cursor.moveToNext();
}
cursor.close();
db.close();
return arr;
Then pass this ArrayList(arr) to the list view using Adaptor and map the values of Pair class to the XML components.
I want to start an activity when i click on one of the item of my RecyclerView. Unfortunately when i click on an item nothing happens and I'm stuck here.
I think the code into the onClick method is right (But maybe I'm wrong). I tried to add a Log.d to see if the listener works but i can't see it in the logcat when i click on an item. I'm new on programming so it can be a stupid error. Thanks for help :)
public class UsersRecyclerAdapter extends RecyclerView.Adapter<UsersRecyclerAdapter.ViewHolder> {
private Context context;
private List<Users> usersList;
public UsersRecyclerAdapter(Context context, List<Users> usersList) {
this.context = context;
this.usersList = usersList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.users_row, parent, false);
return new ViewHolder(view, context);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Users users = usersList.get(position);
holder.firstName.setText(users.getFirstName());
holder.lastName.setText(users.getLastName());
holder.classe.setText(users.getClasse());
String avatarURL = users.getAvatar();
Picasso.get().load(avatarURL).into(holder.avatar);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.i("MyApp","I am here");
context = view.getContext();
Intent intent = new Intent(context, PDFPostListActivity.class);
// String userID = users.getUserID();
// intent.putExtra("userID", userID);
context.startActivity(intent);
}
});
}
EDIT. Here is the root view (users_row):
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
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="wrap_content"
android:layout_margin="5dp">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/imageViewAVATAR"
android:layout_width="50dp"
android:layout_height="50dp"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingTop="10dp" />
<TextView
android:id="#+id/textViewfistName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="10dp"
android:gravity="center"
android:textSize="21sp"
android:textStyle="italic" />
<TextView
android:id="#+id/textViewlastName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="10dp"
android:gravity="center"
android:textSize="21sp"
android:textStyle="italic" />
<TextView
android:id="#+id/textViewclass"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="21sp"
android:textStyle="italic" />
</LinearLayout>
</HorizontalScrollView>
</androidx.cardview.widget.CardView>
What's the root view of the view holder? Set it to be clickable since you set onClickListener on itemView of view holder.
Great thanks to #Mike M. who rapidly answer in the comment below the question. I paste the message:
When you call setOnClickListener() on itemView, it's setting that on the , since that's the outermost View there. The nested within it is preventing it from receiving click events. Assuming that's all that going to be in that layout, then the simplest fix would probably be to simply set the OnClickListener on the instead. You'll need to give it an android:id, find it with findViewById() just like you did the TextViews, and then call setOnClickListener() on that, instead of itemView.
I have a listview in a constraintlayout.
when I try to do a long click on one of the elements of the list, to inflate the context menu, there are 2 problems:
1: It triggers the long click only sometimes, really random
2: After the long click was triggered the "normal" click is also triggered even though the onContextItemSelected returns true (to indicate the event was handled)
for some list elements, I want to have both the onClickListener and the long click for the contextmenu, on others only the contextmenu. (the listview is registered for contextmenu).
Heres the XML of the MainActivity
<?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"
tools:context="it.netknights.piauthenticator.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:backgroundTint="#color/PIBLUE"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="#drawable/ic_add_white_24dp" />
<TextView
android:id="#+id/countdownfield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:backgroundTint="#color/PIBLUE"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#color/PIBLUE"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:popupTheme="#color/PIBLUE"
tools:layout_editor_absoluteY="-57dp" />
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toTopOf="#+id/countdownfield"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar"
app:layout_constraintVertical_bias="1.0" />
</android.support.constraint.ConstraintLayout>
and the XML of the listentry
<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"
android:longClickable="true"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">
<TextView
android:id="#+id/textViewToken"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="124891"
android:textSize="28sp"
android:textStyle="bold"
tools:layout_editor_absoluteY="0dp"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent" />
<!-- android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"-->
<TextView
android:id="#+id/textViewLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="privacyidea something"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginTop="0dp"
app:layout_constraintTop_toBottomOf="#+id/textViewToken"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent" />
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="0dp"
app:layout_constraintTop_toBottomOf="#+id/textViewLabel"
android:layout_marginRight="0dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.517"
/>
</android.support.constraint.ConstraintLayout>
the part of the MainActivity.java
final ListView listview = (ListView) findViewById(R.id.listview);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(view.getContext(), "SHORT itemclick", Toast.LENGTH_SHORT).show();
}
});
registerForContextMenu(listview);
and the getview method from my custom adapter:
#Override
public View getView(final int position, View v, ViewGroup parent) {
if (v == null) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
v = inflater.inflate(R.layout.tokenentry, parent, false);
}
v.setLongClickable(true);
v.setTag(position);
final ProgressBar progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
final Token token = getItem(position);
final TextView tmp2 = (TextView) v.findViewById(R.id.textViewToken);
final TextView tmp1 = (TextView) v.findViewById(R.id.textViewLabel);
if (token.getType().equals(HOTP)) {
progressBar.setVisibility(GONE);
} else {
progressBar.setVisibility(VISIBLE);
//v.setClickable(false);
}
progressBar.setTag(position);
progressBar.setMax(token.getPeriod());
progressBar.getProgressDrawable().setColorFilter(
Color.rgb(0x83, 0xc9, 0x27), android.graphics.PorterDuff.Mode.SRC_IN);
token.setPb(progressBar);
tmp1.setText(token.getLabel());
tmp2.setText(token.getCurrentOTP());
EDIT: thank you for taking your time to post answers.
Ive solved the/my problem: the rootelement of the listentries was a contraintlayout and that doesn't seem to work properly with the scenarios i want, so i changed it so a relativelayout and it now it works perfectly!
hi Cxc the problem might be due to listView registered for both onClick and onLongClick . So instead of setting the onClickListener for the entire list view try setting the onClick listener to only the item view for which you need both onClickListener and long click.
You can set onClickListener to particular views inside getView() method based on their position or view type.
for example,
#Override
public View getView(final int position, View v, ViewGroup parent) {
if (v == null) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
v = inflater.inflate(R.layout.tokenentry, parent, false);
}
v.setLongClickable(true);
v.setTag(position);
if(position % 2 == 0)
{
v.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(v.getContext(), "SHORT itemclick",
Toast.LENGTH_SHORT).show();
}
});
hope this helps
I think you can use both onClick and onLongClick and override the onLongClick method making it returns true to avoid conflict of triggering onClick event
ex:
GridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
<do somthing here>
}
});
GridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, final View view, final int i, long l) {
<do something here>
return true;
}
});
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...