Hi I am trying to create a video journal fragment that has a recyclerview which contains a title, a mood, and a video in each list item. For some reason the videoview is not even showing up. The videofilePath is saving correctly and I've checked with println statements. I'm not getting any errors, but its just completely collapsed. The next list item starts before the video displays.
Here is my ViewHolder class
public class JournalViewHolder extends RecyclerView.ViewHolder{
private TextView title;
private TextView mood;
private VideoView mVideoView;
MediaController mMediaController;
Context mContext;
public JournalViewHolder(View view, Context context){
super(view);
mContext = context;
title = (TextView)view.findViewById(R.id.JournalTitle);
mood = (TextView)view.findViewById(R.id.JournalMood);
mVideoView = (VideoView)view.findViewById(R.id.JournalVideo);
mMediaController = new MediaController(context);
}
public void bind(JournalEntry journalEntry){
title.setText(journalEntry.getTitle());
mood.setText(journalEntry.getMood());
if(journalEntry.getVideoFileName() != null){
Uri uri = Uri.parse(journalEntry.getVideoFileName());
mVideoView.setVideoURI(uri);
mVideoView.requestFocus();
mVideoView.setMediaController(mMediaController);
mVideoView.setZOrderOnTop(true);
mVideoView.start();
}
}
}
Here is my adapter class
public class JournalRecyclerViewAdapter extends RecyclerView.Adapter<JournalViewHolder> {
private List mJournalEntries;
private Context mContext;
public JournalRecyclerViewAdapter(List<JournalEntry> entries, Context context){
mJournalEntries = entries;
mContext = context;
}
#Override
public JournalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.journal_list_items, parent, false);
JournalViewHolder holder = new JournalViewHolder(view, mContext);
return holder;
}
#Override
public void onBindViewHolder(JournalViewHolder holder, int position) {
JournalEntry entry = mJournalEntries.get(position);
holder.bind(entry);
}
#Override
public int getItemCount() {
return mJournalEntries.size();
}
}
Here is my class that initiates the list of items and the recyclerview
public class JournalView extends FragmentLoggingLifeCycler {
private RecyclerView mRecyclerView;
DataAccess mDataAccess;
List<JournalEntry> mEntryList;
public static final String USERNAME_KEY = "username";
public static final String PASSWORD_KEY = "password";
String password;
String username;
User currentUser;
private Context mContext;
public JournalView() {
// Required empty public constructor
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mContext = activity.getApplicationContext();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_journal_view, container, false);
Bundle data = getArguments();
username = data.getString(USERNAME_KEY);
password = data.getString(PASSWORD_KEY);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
mDataAccess = DataAccess.getDataAccess(container.getContext());
currentUser = mDataAccess.getLoginUser(username, password);
mEntryList = mDataAccess.getAllJournals();
//mDataAccess.mDatabase.delete(Scheme.Journal.NAME, null, null);
// mEntryList = trimList(mEntryList, currentUser.getUsername());
// for(int counter = 0; counter < mEntryList.size(); counter++){
// System.out.println(mEntryList.get(counter).getTitle());
// }
mRecyclerView = (RecyclerView)view.findViewById(R.id.JournalList);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(new JournalRecyclerViewAdapter(mEntryList, mContext));
return view;
}
private static List<JournalEntry> trimList(List<JournalEntry> entries, String username){
List<JournalEntry> returnedList = new ArrayList<>();
for(int i = 0; i< returnedList.size(); i++){
System.out.println(entries.get(i).getUsername()+ ", " +username);
if(entries.get(i).getUsername().equals(username)){
returnedList.add(entries.get(i));
}
}
return returnedList;
}
}
and now here are my XML files.
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/JournalList">
List Item files
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_weight="2">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:text="#string/Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/JournalTitle"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:text="#string/Mood"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/JournalMood"/>
</LinearLayout>
<VideoView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/JournalVideo"
android:visibility="visible"/>
Check out this Sample Code for how to have videos playing inside RecyclerView
VideoInRecyclerViewExamples
I'm developing a library named OneItem that may help you.
https://github.com/tbrand/OneItem
In #selectItemAt(int position), start playing video with your arbitrary VideoView(such as MediaPlayer or ExoPlayer).
In #UnSelectItemAt(int position), stop playing video and release it.
Related
I am a new Programmer, actually I was trying to make an app. I was trying to make an activity that uses RecyclerView to Show TextInputEditText with spinner and TextView. It means that I was trying to make an activity that uses Recyclerview and In the layout of Recycler View, I have used Text Input Edit Text and Spinner and TextView. I have put these three in a single layout. But the main problem that I facing is that when I launch my app with my code then it remains blank activity it is not showing TextInputEditText nor spinner and nor TextView.
So the conclusion is I want to show [TextInputEditText, Spinner and TextView] in RecyclerView But my code is returning Blank Activity.
Here is my code:-
It is my adapter class:-
public class SpecialHoursAdapter extends RecyclerView.Adapter<SpecialHoursAdapter.SpecialHourHolder> {
// private ArrayList[] mDataSet;
private List<SpecialHorusModal> modal = new ArrayList<>();
private Context context;
public SpecialHoursAdapter(Context context) {
this.context = context;
}
#NonNull
#Override
public SpecialHourHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.special_hours_layout_card, parent, false);
return new SpecialHourHolder(view);
}
#Override
public void onBindViewHolder(#NonNull SpecialHourHolder holder, int position) {
}
#Override
public int getItemCount() {
return modal.size();
}
public static class SpecialHourHolder extends RecyclerView.ViewHolder {
private TextInputEditText editText;
private Spinner spinner;
private TextView textView;
public SpecialHourHolder(#NonNull View itemView) {
super(itemView);
editText = itemView.findViewById(R.id.special_hours_editor);
spinner = itemView.findViewById(R.id.spinner_special_hours_date);
textView = itemView.findViewById(R.id.time_picker_special_horus);
}
}
}
It is My MainActivity:-
public class SpecialHoursActivity extends AppCompatActivity {
private RecyclerView containerRecyclerView;
private RecyclerView.LayoutManager first, container;
private SpecialHoursAdapter adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_special_horus);
// mainRecyclerView = findViewById(R.id.activity_special_horus_main_recyclerview);
containerRecyclerView = findViewById(R.id.layout_container_recyclerview_special_hours);
// mainRecyclerView.setHasFixedSize(true);
containerRecyclerView.setHasFixedSize(true);
first = new LinearLayoutManager(this);
container = new LinearLayoutManager(this);
// mainRecyclerView.setLayoutManager(first);
containerRecyclerView.setLayoutManager(container);
containerRecyclerView.setAdapter(adapter);
}
}
Here is my RecyclerView Layout:-
<?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="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/special_hours_editor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Special Hours"
android:inputType="text"
android:maxLength="20" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="#+id/spinner_special_hours_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/time_picker_special_horus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:gravity="end"
android:text="00:00" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
My Main Layout -
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_special_horus_main_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="vertical">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="#+id/layout_container_recyclerview_special_hours"
android:orientation="vertical"
android:scrollbars="vertical">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
I have not used any modal class because I don't know how to use it with Widgets.
you need to pass the data to your adapter
public SpecialHoursAdapter(Context context,List<SpecialHorusModal> data) {
this.context = context;
this.model=data; //it will show your recyclerview
}
we could not show the Recyclerview with empty data
You need to populate the data your Adapter holds, adapter with empty data will obviously show no items.
public class SpecialHoursAdapter extends RecyclerView.Adapter<SpecialHoursAdapter.SpecialHourHolder> {
private List<SpecialHorusModal> items = new ArrayList<>();
private Context context;
public SpecialHoursAdapter(Context context) {
this.context = context;
}
//Call this in onClick of your button, passing it the object to add
public void addItem(SpecialHoursModal item) {
items.add(item);
notifyDataSetChange(); //This is important
}
#NonNull
#Override
public SpecialHourHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.special_hours_layout_card, parent, false);
return new SpecialHourHolder(view);
}
#Override
public void onBindViewHolder(#NonNull SpecialHourHolder holder, int position) {
//Bind the data to view for the object at this position
SpecialHorusModal item = items.get(position);
//...
}
#Override
public int getItemCount() {
return items.size();
}
public static class SpecialHourHolder extends RecyclerView.ViewHolder {
private TextInputEditText editText;
private Spinner spinner;
private TextView textView;
public SpecialHourHolder(#NonNull View itemView) {
super(itemView);
editText = itemView.findViewById(R.id.special_hours_editor);
spinner = itemView.findViewById(R.id.spinner_special_hours_date);
textView = itemView.findViewById(R.id.time_picker_special_horus);
}
}
}
When your button is clicked, or you need to add an item:
adapter.addItem(new SpecialHorusModal(...));
I'm writing a shopping list app that will save data to a Firebase Realtime database and update the screen in real time. As of right now I have it so that when you click the "+ List item" button, it adds a ShoppingListItem to the database with the name "test". It does that correctly, but it isn't updating the screen. I've double checked that the methods are being called, but the screen isn't reflecting the updated data. I have also tried using notifyDataSetChanged() and that hasn't seemed to help either.
This is the code for the ShoppingListFragment:
public class ShoppingListFragment extends Fragment {
private ArrayList<String> listItems = new ArrayList<String>();
private ListView mListView;
private TextView addItemButton;
private LinearLayout ll;
private RecyclerView rv;
private FirebaseRecyclerAdapter<ShoppingListItem, ShoppingListHolder> firebaseRecyclerAdapter;
private DatabaseReference mDatabase;
public ShoppingListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
mDatabase = FirebaseDatabase.getInstance().getReference();
//get reference to user
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
Query query = mDatabase.child("users").child(uid).child("shopping");
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_shopping_list, container, false);
rv = view.findViewById(R.id.shopping_list);
rv.setLayoutManager(new LinearLayoutManager(getContext()));
// find the + List Item button
final TextView addCheckBox = view.findViewById(R.id.add_check_box);
addCheckBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addNewCheckBox(container);
}
});
FirebaseRecyclerOptions<ShoppingListItem> options = new FirebaseRecyclerOptions.Builder<ShoppingListItem>()
.setQuery(query, ShoppingListItem.class)
.build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ShoppingListItem, ShoppingListHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull ShoppingListHolder holder, int position, #NonNull ShoppingListItem item) {
holder.setItem(item);
}
#NonNull
#Override
public ShoppingListHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.shopping_list_item, parent, false);
return new ShoppingListHolder(view);
}
};
return view;
}
#Override
public void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
rv.setAdapter(firebaseRecyclerAdapter);
}
#Override
public void onStop() {
super.onStop();
if (firebaseRecyclerAdapter != null) {
firebaseRecyclerAdapter.stopListening();
}
}
public void addNewCheckBox(ViewGroup container) {
String key = mDatabase.child("users").child(getUid()).child("shopping_list").push().getKey();
ShoppingListItem item = new ShoppingListItem("test");
mDatabase.child("users").child(getUid()).child("shopping_list").child(key).setValue(item);
firebaseRecyclerAdapter.notifyDataSetChanged();
}
public int convertToPx(int input) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
int px = (int) (input * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
private class ShoppingListHolder extends RecyclerView.ViewHolder {
private final EditText itemName;
public ShoppingListHolder(View itemView) {
super(itemView);
itemName = itemView.findViewById(R.id.item_name);
}
public void setItem(ShoppingListItem item) {
itemName.setText(item.getItemName());
}
}
private String getUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
}
and the ShoppingListItem:
public class ShoppingListItem {
private String itemName;
private String type;
private String unit;
private int quantity;
private String location;
public ShoppingListItem() {
}
public ShoppingListItem(String name) {
this.itemName = name;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
}
XML for the shopping list view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/home_fragment_main_layout"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.jggdevelopment.wannacook.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Shopping List"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/shopping_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:clipToPadding="false"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/add_check_box"
android:text="+ List item"
android:textSize="16sp"
android:layout_marginStart="40dp"
android:layout_marginTop="16dp"/>
</LinearLayout>
and XML for each line item in the shopping list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/item_name"
android:layout_weight="1"
android:layout_marginStart="12dp"
android:layout_marginEnd="32dp"
android:inputType="text"
android:background="#android:color/transparent"
/>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:id="#+id/xbutton"
android:layout_marginEnd="12dp"
android:src="#drawable/ic_close_white_24dp"
android:layout_gravity="center_vertical"/>
</LinearLayout>
This is not working because you forgot to set the adapter in the onCreate() method. To solve this, add rv.setAdapter(firebaseRecyclerAdapter);, right before you are returning the view like this:
rv.setAdapter(firebaseRecyclerAdapter);
return view;
And you can remove that line of code from the onStart() method because is not needed there.
If you are interested, I have created a tutorial in which I'm explaining step by step, how to build a Shopping List App using Cloud Firestore and Android.
I know this question was asked before but even after looking for all the answer
I couldn't find anything relevant. I am basically trying to display a list of items inside a fragment using recycler view, but it saysNo adapter attached; skipping layout even though I have attached an adapter.
Note: I am using a Tab Layout where there are three tabs and a fragment inside each Tab. I am trying to display the recycler view list in one of the fragment.
Here is my Adapter class:
public class SongAdapter extends RecyclerView.Adapter<SongAdapter.SongViewHolder> {
ArrayList<SongData> songList;
public SongAdapter(ArrayList songList) {
this.songList = songList;
}
//Getting hold of each item of the RecyclerView
public static class SongViewHolder extends RecyclerView.ViewHolder {
ImageView albumArt;
TextView Title,Artist;
public SongViewHolder(View itemView) {
super(itemView);
albumArt = (ImageView)itemView.findViewById(R.id.AlbumImage);
Title= (TextView)itemView.findViewById(R.id.Title);
Artist = (TextView)itemView.findViewById(R.id.Artist);
}
}
#Override
public SongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.music_tiles,parent,false);
SongViewHolder svh= new SongViewHolder(view);
return svh;
}
#Override
public void onBindViewHolder(SongViewHolder holder, int position) {
SongData songData = songList.get(position);
holder.Title.setText(songData.Title);
holder.Artist.setText(songData.Artist);
holder.albumArt.setImageResource(songData.ImageId);
}
#Override
public int getItemCount() {
return songList.size();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
Fragment code:
public class musicFrag extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public musicFrag() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static musicFrag newInstance(String param1, String param2) {
musicFrag fragment = new musicFrag();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_music, container, false);
//Initializing RecyclerView , SongAdapter, LinerLayoutManager
SongData songData =new SongData();
RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager( new LinearLayoutManager(getActivity()));
SongAdapter songAdapter = new SongAdapter(songData.InitializeData());
recyclerView.setAdapter(songAdapter);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
Fragment layout:
<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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.dannproductions.musify.MainActivity$PlaceholderFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
SongData Class :
public class SongData {
String Title,Artist;
int ImageId;
public SongData() {
};
public SongData(String title, String Artist, int ImageId) {
this.Title = Title;
this.Artist = Artist;
this.ImageId = ImageId;
}
ArrayList<SongData> songList;
public ArrayList<SongData> InitializeData(){
songList = new ArrayList<SongData>();
songList.add(new SongData("Aman","Chatterjee",R.drawable.round));
songList.add(new SongData("Aman","Chatterjee",R.drawable.round));
songList.add(new SongData("Aman","Chatterjee",R.drawable.round));
songList.add(new SongData("Aman","Chatterjee",R.drawable.round));
songList.add(new SongData("Aman","Chatterjee",R.drawable.round));
return songList;
}
}
Here is the RecyclerView item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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.support.v7.widget.CardView
android:id="#+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/AlbumImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginEnd="10dp"
android:src="#drawable/round"
app:civ_border_color="#d35400"
app:civ_border_width="4dp" />
<TextView
android:id="#+id/Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="30dp"
android:layout_toEndOf="#id/AlbumImage"
android:text="TextView"
android:textSize="25sp" />
<TextView
android:id="#+id/Artist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/Title"
android:layout_centerHorizontal="true"
android:layout_toEndOf="#id/AlbumImage"
android:text="TextView" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
I pasted your adapter and recyclerview code in my android studio. and i found no bug in your list filling code. Here is how your list looks.
So double check your tablayout and fragment code if you are having some issue.
I have a RecyclerView that contains a bunch of CardViews. Each CardView then has its own RecyclerView in it. The problem is that only the "main" RecyclerView is scrolling. The nested one in the CardView is not getting focus, so I can't scroll it. How can i make it so that both will be scrollable?
Parent Layout
<android.support.design.widget.CoordinatorLayout android:id="#+id/coordinatorLayout_main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_savedFiles"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:padding="8dp"/>
</android.support.design.widget.CoordinatorLayout>
Parent Adapter
public class AdapterSavedFilesCards extends RecyclerView.Adapter<AdapterSavedFilesCards.ViewHolderSavedFilesCard>{
/**
* List of cards in the recycler view
*/
private final ArrayList<CardViewSavedFiles> cards;
private final Context context;
public AdapterSavedFilesCards(final Context context){
this.context = context;
cards = new ArrayList<>(Arrays.asList(new CardViewSavedFiles[]{
new CardViewSavedFiles("Card One"),
new CardViewSavedFiles("Card Two"),
new CardViewSavedFiles("Card Three")
}));
}
#Override
public ViewHolderSavedFilesCard onCreateViewHolder(ViewGroup parent, int viewType){
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_saved_files, parent, false);
return new AdapterSavedFilesCards.ViewHolderSavedFilesCard(view);
}
#Override
public void onBindViewHolder(ViewHolderSavedFilesCard holder, int position){
//Get the card at this position
final CardViewSavedFiles card = cards.get(position);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context));
holder.recyclerView.setItemAnimator(null);
holder.recyclerView.setHasFixedSize(true);
holder.recyclerView.setAdapter(card.getAdapterSavedFiles());
holder.title.setText(card.getTitle());
holder.subTitle.setText("Subtitle");
((CardView)holder.itemView).setCardBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), card.getBackgroundColor()));
}
#Override
public int getItemCount(){
return cards.size();
}
public ArrayList<CardViewSavedFiles> getCards(){
return cards;
}
protected class ViewHolderSavedFilesCard extends RecyclerView.ViewHolder{
private final TextView title;
private final TextView subTitle;
private final RecyclerView recyclerView;
public ViewHolderSavedFilesCard(final View itemView){
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
subTitle = (TextView) itemView.findViewById(R.id.subTitle);
recyclerView = (RecyclerView) itemView.findViewById(R.id.recyclerView);
}
}
}
Child Layout
<android.support.v7.widget.CardView
android:id="#+id/cardView_savedFactors"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/rootView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/subTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="128dp"
android:paddingStart="#dimen/content_padding_start"
android:paddingEnd="#dimen/content_padding_end"/>
<Button
android:id="#+id/button"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.v7.widget.CardView>
Child Adapter
public class AdapterSavedFiles extends RecyclerView.Adapter<AdapterSavedFiles.ViewHolderSavedFiles>{
private final ArrayList<File> files = new ArrayList<>();
private final FILE_TYPE fileType;
public AdapterSavedFiles(final Context context, final FILE_TYPE fileType){
this.fileType = fileType;
switch (fileType){
case ONE:
files.addAll(Arrays.asList(FileManager.getInstance(context).getFilesDirOne().listFiles()));
break;
case TWO:
files.addAll(Arrays.asList(FileManager.getInstance(context).getFilesDirTwo().listFiles()));
break;
}
}
#Override
public ViewHolderSavedFiles onCreateViewHolder(ViewGroup parent, int viewType){
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_saved_file, parent, false);
return new AdapterSavedFiles.ViewHolderSavedFiles(view);
}
#Override
public void onBindViewHolder(ViewHolderSavedFiles holder, int position){
holder.fileName.setText("List item " + position);
switch (fileType){
case ONE:
holder.icon.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(holder.itemView.getContext(), R.color.primary)));
holder.icon.setText("P");
break;
case TWO:
holder.icon.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(holder.itemView.getContext(), R.color.green)));
holder.icon.setText("F");
break;
}
}
#Override
public int getItemCount(){
return files.size();
}
public ArrayList<File> getFiles(){
return files;
}
protected class ViewHolderSavedFiles extends RecyclerView.ViewHolder{
private final TextView fileName;
private final TextView icon;
public ViewHolderSavedFiles(final View itemView){
super(itemView);
icon = (TextView) itemView.findViewById(R.id.icon);
fileName = (TextView) itemView.findViewById(R.id.file_name);
}
}
}
Layout Screenshot
You may use ListView in Child adapter in onBindViewHolder instead of TextView.This may solve scrolls child items inside CardView.
I have a simple listView via a custom adapter. Each row in the list view is composed of a ImageButton and TextView.
The idea is to change the ImageButton when user taps on it and it does not work. However, ImageButton changes for the views that are scrolled and recycled. I mean, when user scrolls down the list and comes back to the top and tap on the ImageButton it works as expected for those rows that were scrolled and back again.
Can you guys help me out what i'm missing? I'm extremely new to Android and have been stuck around this for about a week now trying to fix this.
Here's the APK for the sample test app:
https://www.dropbox.com/s/pzlahtqkgj010m8/app-ListViewExample.apk?dl=0
Here are the relevant parts of my code:
avtivity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/listView"
/>
</RelativeLayout>
and to render the single row in the ListView the following xml is utilized:
single_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageButton"
android:src="#drawable/b"
android:layout_weight="2"
style="#style/ListView.first"
android:layout_gravity="center"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView"
android:layout_weight="10"
android:layout_gravity="center"
/>
</LinearLayout>
coming to the Java code,
MainActivity.java is
public class MainActivity extends AppCompatActivity {
String[] titles;
ListView list;
private listViewAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
titles = res.getStringArray(R.array.titles);
list = (ListView) findViewById(R.id.listView);
adapter = new listViewAdapter(this, titles);
list.setAdapter(adapter);
}
}
and the custom adapter listViewAdapter.java look like this
class sListItem {
public ImageButton button;
public TextView text;
public boolean active;
}
public class listViewAdapter extends ArrayAdapter<String> {
private final String[] titles;
Context context;
private int size = 15;
public sListItem mp[] = new sListItem[size];
public listViewAdapter(Context context, String[] titles) {
super(context, R.layout.single_row, R.id.imageButton, titles);
this.context = context;
this.titles = titles;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.single_row, parent, false);
if(mp[position] == null)
mp[position] = new sListItem();
mp[position].button = (ImageButton) row.findViewById(R.id.imageButton);
mp[position].button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mp[position].active = !mp[position].active;
setIcon(position, mp[position].active);
}
});
mp[position].text = (TextView) row.findViewById(R.id.textView);
mp[position].text.setText(titles[position]);
setIcon(position, mp[position].active);
return row;
}
private void setIcon(int position, boolean active) {
Drawable drawable;
if(active){
drawable = getContext().getResources().getDrawable(R.drawable.a);
} else {
drawable = getContext().getResources().getDrawable(R.drawable.b);
}
mp[position].button.setImageDrawable(drawable);
}
}
EDIT: Added link to sample test app.
You should tell adapter to update by calling notifydatasetchanged in the click listener
mp[position].button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mp[position].active = !mp[position].active;
setIcon(position, mp[position].active);
notifydatasetchanged();
}
});