I have 6 fragments in a Sliding tab layout. All of them have RecyclerView implemented in them. I have populated the RecyclerView. But I one of the fragments does not allow me to scroll, but the rest are working fine.
See the gif below:
This is my problem
Genres.java
public class Genres extends Fragment {
private static final String TAG = "Genres";
RecyclerView recyclerView_genre;
GenresAdapter genresAdapter;
ArrayList<GenresModel> Genrelist = new ArrayList<>();
long genreId;
String genreName;
Cursor genrecursor;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.genres_activity, container, false);
recyclerView_genre = view.findViewById(R.id.recyclerView_genre);
recyclerView_genre.setHasFixedSize(true);
LinearLayoutManager genreLayout = new LinearLayoutManager(getContext());
recyclerView_genre.setLayoutManager(genreLayout);
String[] proj1 = {MediaStore.Audio.Genres.NAME, MediaStore.Audio.Genres._ID};
genrecursor=getActivity().getContentResolver().query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,proj1,null, null, null);
if (genrecursor != null) {
if (genrecursor.moveToFirst()) {
do {
genreId = genrecursor.getLong(genrecursor.getColumnIndexOrThrow(MediaStore.Audio.Genres._ID));
genreName = genrecursor.getString(genrecursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME));
GenresModel genresModel = new GenresModel(genreId,genreName );
Genrelist.add(genresModel);
Collections.sort(Genrelist, new Comparator<GenresModel>() {
#Override
public int compare(GenresModel lhs, GenresModel rhs) {
return lhs.getGenreName().compareTo(rhs.getGenreName());
}
});
} while (genrecursor.moveToNext());
}
}
genrecursor.close();
genresAdapter = new GenresAdapter(getContext(),Genrelist);
recyclerView_genre.setAdapter(genresAdapter);
genresAdapter.notifyDataSetChanged();
return view;
}
GenresAdapter.java
public class GenresAdapter extends RecyclerView.Adapter<GenresAdapter.GenresHolder> {
Context gContext;
ArrayList<GenresModel> GenreList = new ArrayList<>();
public GenresAdapter(Context gContext, ArrayList<GenresModel> genreList) {
this.gContext = gContext;
GenreList = genreList;
}
#Override
public GenresAdapter.GenresHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view3 = LayoutInflater.from(gContext).inflate(R.layout.row_genre, parent, false);
return new GenresHolder(view3);
}
#Override
public void onBindViewHolder(GenresAdapter.GenresHolder holder, int position) {
final GenresModel genresModel1 = GenreList.get(position);
holder.genreText.setText( genresModel1.getGenreName());
}
#Override
public int getItemCount() {
return GenreList.size();
}
public class GenresHolder extends RecyclerView.ViewHolder {
TextView genreText;
public GenresHolder(View itemView) {
super(itemView);
genreText = itemView.findViewById(R.id.genreText);
}
}
}
activity_genre.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_genre"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="130dp"
>
</android.support.v7.widget.RecyclerView>
</LinearLayout>
row_genre.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:paddingTop="35dp"
>
<TextView
android:id="#+id/genreText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="14sp"
/>
</LinearLayout>
I found out the solution myself. Actually the the problem was with the viewpager transformation. I applied https://github.com/geftimov/android-viewpager-transformers/wiki/CubeOutTransformer to my viewpager and for some reason my first 3 fragments were working and rest were not!
Related
I am using RecyclerView in a fragment, it is generate a NullPointerException and I cannot understand the reason.
Here is my fragment activity:
public class Recharges extends Fragment {
public RecyclerView recyclerView;
private List<GetRecharge> rechargeList = new ArrayList<>();
public RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
ImageView image1, image2;
#Nullable #Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Toolbar myToolbar = (Toolbar) getActivity().findViewById(R.id.my_toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(myToolbar);
View rootView = inflater.inflate(R.layout.recharges, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview1);
recyclerView.setHasFixedSize(true);
final FragmentActivity c = getActivity();
layoutManager = new LinearLayoutManager(c);
recyclerView.setLayoutManager(layoutManager);
adapter = new Adapterrecharge(rechargeList);
recyclerView.setAdapter(adapter);
prepareRechargeData();
return rootView;
}
private void prepareRechargeData() {
GetRecharge recharge = new GetRecharge("Mad Max: Fury Road" );
rechargeList.add(recharge);
adapter.notifyDataSetChanged();
}
}
Here the adapter class:
public class Adapterrecharge extends RecyclerView.Adapter<Adapterrecharge.MyViewHolder> {
private List<GetRecharge> rechargeList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
ImageView image;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
}
}
public Adapterrecharge(List<GetRecharge> rechargeList) {
this.rechargeList = rechargeList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.rechargelist, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
GetRecharge recharge = rechargeList.get(position);
holder.title.setText(recharge.getTitle());
}
#Override
public int getItemCount() {
return rechargeList.size();
}
}
I seem to be inflating the correct layout but still getting the error.
here is the logcat error
java.lang.NullPointerException
at com.example.aadesh.walletuncle.Adapterrecharge.onBindViewHolder(Adapterrecharge.java:53)
at com.example.aadesh.walletuncle.Adapterrecharge.onBindViewHolder(Adapterrecharge.java:21)
here is the recyclerview item layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/text"/>
here is the main layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
<TextView
android:text="Recharge"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large"
android:textColor="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView4"
android:layout_weight="1" />
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:id="#+id/recyclerview1">
</android.support.v7.widget.RecyclerView>
there are couple of problems
you are populating prepareRechargeData() list data after you have set your adapter - so your list rechargelist doesn't have any data
in your onCreateViewHolder() your are using wrong layout R.layout.rechargelist
in your view Holder you are giving wrong id for textview R.id.title
try this:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Toolbar myToolbar = (Toolbar) getActivity().findViewById(R.id.my_toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(myToolbar);
View rootView = inflater.inflate(R.layout.recharges, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview1);
recyclerView.setHasFixedSize(true);
final FragmentActivity c = getActivity();
layoutManager = new LinearLayoutManager(c);
recyclerView.setLayoutManager(layoutManager);
/*recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter((RecyclerView.Adapter) adapter);*/
prepareRechargeData();
adapter = new Adapterrecharge(rechargeList);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
return rootView;
}
Change your adapter to:
public class Adapterrecharge extends RecyclerView.Adapter<Adapterrecharge.MyViewHolder> {
private List<GetRecharge> rechargeList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
ImageView image;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.text);
}
}
public Adapterrecharge(List<GetRecharge> rechargeList) {
this.rechargeList = rechargeList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_layout, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
GetRecharge recharge = rechargeList.get(position);
holder.title.setText(recharge.getTitle());
}
#Override
public int getItemCount() {
return rechargeList.size();
}
}
You are miss matching id of Textview.
Instead of
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/text"/>
</LinearLayout>
Use this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/title"/>
</LinearLayout>
As you are using wrong id of Textview in MyViewHolder class.
The problem is due to mismatch ids. ID of TextView in xml ("text") and the one inflated in ViewHolder class ("title") are different.
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/text"/>
Adapter class
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
}
In my app,I get some data from my server. They are displayed fine,but when I pass them in my Detailed Fragment,then all views are null:(.
So here is my code.
public class MainActivityFragment extends Fragment {
public static final String TAG = "AelApp";
public static ArrayList<MyModel> listItemsList;
RecyclerView myList;
public static MatchReportsAdapter adapter;
public MainActivityFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateMatchReport();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
getActivity().setTitle("Match Report");
View rootView = inflater.inflate(R.layout.fragment_main_activity, container, false);
listItemsList = new ArrayList<>();
myList = (RecyclerView)rootView.findViewById(R.id.listview_match_reports);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
myList.setHasFixedSize(true);
myList.setLayoutManager(linearLayoutManager);
adapter = new MatchReportsAdapter(getActivity(), listItemsList);
myList.setAdapter(adapter);
return rootView;
}
public void updateMatchReport(){
Intent i = new Intent(getActivity(), MatchReport.class);
getActivity().startService(i);
}
}
Adapter
public class MatchReportsAdapter extends
RecyclerView.Adapter<MatchReportsAdapter.RowHolder>{
private List<MyModel> reportsList;
private Context mContext;
private ImageLoader mImageLoader;
private int focused = 0;
public MatchReportsAdapter(Activity activity, List<MyModel> reportsLists){
this.reportsList = reportsLists;
this.mContext=activity;
}
#Override
public RowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_items,null);
final RowHolder holder = new RowHolder(v);
return holder;
}
#Override
public void onBindViewHolder(RowHolder holder, int position) {
final MyModel listItems = reportsList.get(position);
holder.itemView.setSelected(focused==position);
holder.getLayoutPosition();
mImageLoader = AppController.getInstance().getImageLoader();
holder.thumbnail.setImageUrl(listItems.getImage(),mImageLoader);
holder.thumbnail.setDefaultImageResId(R.drawable.reddit_placeholder);
holder.name.setText(Html.fromHtml(listItems.getTitle()));
holder.relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String article = listItems.getArticle();
String image = listItems.getImage();
Intent i = new Intent(mContext, DetailedActivity.class);
i.putExtra("articleKey",article);
i.putExtra("imageKey",image);
mContext.startActivity(i);
}
});
}
#Override
public int getItemCount() {
return reportsList.size();
}
public class RowHolder extends RecyclerView.ViewHolder{
protected NetworkImageView thumbnail;
protected TextView name;
protected RelativeLayout relativeLayout;
public RowHolder(View itemView) {
super(itemView);
this.relativeLayout = (RelativeLayout)
itemView.findViewById(R.id.recLayout);
this.thumbnail =
(NetworkImageView)itemView.findViewById(R.id.thumbnail);
this.name = (TextView)itemView.findViewById(R.id.title);
}
}
}
DetailedActivity
public class DetailedActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed);
if(savedInstanceState == null){
getSupportFragmentManager()
.beginTransaction()
.add(R.id.detailed_match_reports,new DetailedActivityFragment())
.commit();
}
}
}
DetailedActivityFragment
public class DetailedActivityFragment extends Fragment {
TextView articleTextView;
String image;
String article;
ImageView imageView;
public DetailedActivityFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_detailed_activity, container, false);
articleTextView = (TextView)getActivity().findViewById(R.id.articleTextView);
imageView = (ImageView)getActivity().findViewById(R.id.imageNews);
Intent i = getActivity().getIntent();
article = i.getStringExtra("articleKey");
image = i.getStringExtra("imageKey");
Picasso.with(getActivity()).load(image).into(imageView);
articleTextView.setText(article);
return v;
}
}
All of my data are passed after clicking a row good. I know this as I debug the following lines.
article = i.getStringExtra("articleKey");
image = i.getStringExtra("imageKey");
and see that both String variables are not null. However,the both views(TextView,ImageView) of my detailed fragment are null.
Maybe I am doing something wrong with my xml file,and I don't see it.
activity_main.xml
<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"
android:id="#+id/match_reports"
tools:context="theo.testing.androidservices.fragments.MainActivityFragment">
</FrameLayout>
fragment_main_activity
<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:id="#+id/recLayout"
tools:context=".activities.MainActivity"
android:background="#fff">
<android.support.v7.widget.RecyclerView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/listview_match_reports"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
/>
</RelativeLayout>
activity_detailed.xml
<?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:id="#+id/detailed_match_reports"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="theo.testing.androidservices.activities.DetailedActivity"
tools:ignore="MergeRootFrame">
</FrameLayout>
and finally
fragment_detailed_activity
<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/imageNews"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="xcvxcvxcv"
android:textColor="#000"
android:layout_marginTop="5dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/articleTextView"/>
</ScrollView>
What am I missing?
Thanks
Theo.
Change these
articleTextView = (TextView)getActivity().findViewById(R.id.articleTextView);
imageView = (ImageView)getActivity().findViewById(R.id.imageNews);
to
articleTextView = (TextView)v.findViewById(R.id.articleTextView);
imageView = (ImageView)v.findViewById(R.id.imageNews);
You'r passing data to DetailActivity. So first retrieve in DetailActivity and then pass to DetailFragment.
Also you need to pass data to DetailFragment using Bundle with setArguments(bundle)
Your Textview articleTextView is in the fragment but you are finding it in the activitys xml:
articleTextView = (TextView)getActivity().findViewById(R.id.articleTextView);
insetad you should do:
articleTextView = (TextView)(v.findViewById(R.id.articleTextView));
Do the same for Imageviewl.
I am trying to handle item clicks on a listview using either the regular AdapterView.OnItemClickedListener or the ButterKnife #OnItemSelected annotation, but none of them work.
I have tried logging to see if any of the clicks come through by:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(Overview.class.getSimpleName(), String.valueOf(position));
}
and
#OnItemClick(R.id.tracks)
void onItemSelected(int position){
Log.e("Tracks", String.valueOf(position));
}
but none of them work. What could be the issue?
The code for my class is:
public class Overview extends Fragment implements AdapterView.OnItemClickListener {
private static final String DATA = "data";
public static final int ARTIST = 1;
public static final int ALBUM = 2;
public static final int PLAYLIST = 3;
int source;
RealmList<Track> trackList;
RealmList<Album> albumList;
#BindView(R.id.tracks)
ExpandableHeightListView tracks;
#BindView(R.id.albums)
RecyclerView albums;
#BindView(R.id.albumsLayout)
LinearLayout albumsLayout;
#OnItemClick(R.id.tracks)
void onItemSelected(int position){
Log.e("Tracks", String.valueOf(position));
}
#OnClick({R.id.all_tracks, R.id.all_albums})
public void showMore(View view) {
switch (view.getId()) {
case R.id.all_tracks:
break;
case R.id.all_albums:
break;
}
}
public Overview newInstance(Wrapper wrapper) {
Bundle bundle = new Bundle();
Overview overview = new Overview();
bundle.putParcelable(DATA, Parcels.wrap(wrapper));
overview.setArguments(bundle);
return overview;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview, container, false);
ButterKnife.bind(this, view);
tracks.setExpanded(true);
tracks.setOnItemClickListener(this);
albums.setLayoutManager(new LinearLayoutManager(getActivity(),
LinearLayoutManager.HORIZONTAL, false));
albums.setNestedScrollingEnabled(false);
Wrapper wrapper = Parcels.unwrap(getArguments().getParcelable(DATA));
trackList = wrapper.getTracks();
albumList = wrapper.getAlbums();
source = wrapper.getSource();
setItems(source);
return view;
}
private void setItems(int source) {
if (!trackList.isEmpty()) {
TrackListAdapter trackListAdapter;
switch (source) {
case ARTIST:
RealmList<Track> realmList = new RealmList<>();
ArrayList<Track> list = new ArrayList<>(trackList.size() > 10 ?
trackList.subList(0, 10) : trackList);
realmList.addAll(list);
trackListAdapter = new TrackListAdapter(getActivity(),
R.layout.track_list_item, realmList);
tracks.setAdapter(trackListAdapter);
break;
case PLAYLIST:
trackListAdapter = new TrackListAdapter(getActivity(),
R.layout.track_list_item, trackList);
tracks.setAdapter(trackListAdapter);
break;
case ALBUM:
trackListAdapter = new TrackListAdapter(getActivity(),
R.layout.album_track_list_item, trackList);
tracks.setAdapter(trackListAdapter);
break;
}
}
if (albumList != null && !albumList.isEmpty()) {
albumsLayout.setVisibility(View.VISIBLE);
AlbumsAdapter albumsAdapter = new AlbumsAdapter(getActivity(), albumList);
albums.setAdapter(albumsAdapter);
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(Overview.class.getSimpleName(), String.valueOf(position));
}
}
It's layout file is:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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:background="#color/DarkBodyBackground"
android:orientation="vertical">
<TextView
style="#style/DarkThemeHeaderText"
android:text="Top Tracks" />
<com.radioafrica.music.view.ExpandableHeightListView
android:id="#+id/tracks"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/DarkCardBackgroundColor"
android:dividerHeight="1dip"
android:footerDividersEnabled="true"
android:headerDividersEnabled="true" />
<TextView
android:id="#+id/all_tracks"
style="#style/ShowAllText" />
<LinearLayout
android:id="#+id/albumsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical"
android:visibility="gone">
<TextView
style="#style/DarkThemeHeaderText"
android:text="Albums" />
<android.support.v7.widget.RecyclerView
android:id="#+id/albums"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/all_albums"
style="#style/ShowAllText" />
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
So I have this list of city objects (which contain an image, the name of the city, and a integer value). And for each of these city objects I want to programatically create a new cardView and insert it into a fragment. Currently, nothing shows up...
Here is my fragment xml code.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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="match_parent"
android:orientation="vertical"
android:paddingTop="24dp"
android:id="#+id/fragCards_LL">
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
Here is the code for my fragment activity.
public class FragmentCards extends Fragment
{
private ArrayList<CityFolders> cityFolders = new ArrayList<>();
private OnCardsFragmentListener mListener;
private LinearLayout linearLayout;
private View view;
public FragmentCards() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_fragment_cards, container, false);
setUpLinearLayout();
setUpCityFolders();
//TextView myText = (TextView) view.findViewById(R.id.fragCards_numberOfCardsTextContent);
//Toast.makeText(getActivity(), myText.getText(), Toast.LENGTH_SHORT).show();
return inflater.inflate(R.layout.fragment_fragment_cards, container, false);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnCardsFragmentListener)
{
mListener = (OnCardsFragmentListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnCheeseCategoriesFragmentListener");
}
}
private void setUpLinearLayout()
{
linearLayout = (LinearLayout) view.findViewById(R.id.fragCards_LL);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(new NestedScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
private void setUpCityFolders()
{
if(!Global_Class.getInstance().getValue().cityFoldersArrayList.isEmpty())
{
cityFolders = Global_Class.getInstance().getValue().cityFoldersArrayList;
for(CityFolders cityFolder : cityFolders)
{
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(64,64,64,64);
lp.height = 200;//180dp = 720pixels
lp.width = 1408;//330dp = 1320 pixels.
CardView cityCardView = new CardView(getActivity());// ERROR
cityCardView.setBackgroundColor(000000);
cityCardView.setLayoutParams(lp);
linearLayout.addView(cityCardView, 0);
}
}
}
public interface OnCardsFragmentListener
{
void disableCollapse();
}
}
So, don't know what I am doing wrong here... hope someone can help, maybe point out what im doing wrong?
Also, in my cardView, going horizontally, I want to have an imageview, then a textview, followed by another textview. How would I inflate those parts of the cardView and fill them with an image, and 2 texts from my cityFolder object? Hope you guys can help me with an answer!
Cheers
EDIT:
So i implemented a recycler view and..nothing shows up on the screen... This recycler view just holds simple views with each view having an imageview and a textview, and nothing shows up..
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp"
android:id="#+id/fragCards_LL">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/fragCards_RecyclerView">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Here is my xml code for the view for each item in the recycler view
<?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">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/fullstar"
android:id="#+id/fragCardsCity_imageview"
android:layout_gravity="center_vertical"
android:padding="8dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Star City"
android:layout_gravity="center_vertical"
android:id="#+id/fragCardsCity_textView"
android:padding="8dp"/>
</LinearLayout>
And finally, here is my java code.
public class FragmentCards extends Fragment
{
private ArrayList<CityFolders> cityFolders = new ArrayList<>();
private LinearLayout linearLayout;
private View rootView;
private RecyclerView recyclerView;
private CityViewAdapter cityAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.fragment_cards, container, false);
linearLayout = (LinearLayout) rootView.findViewById(R.id.fragCards_LL);
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragCards_RecyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
cityAdapter = new CityViewAdapter(getActivity(),getData());
recyclerView.setAdapter(cityAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
return rootView;
}
public static ArrayList<myData> getData()
{
ArrayList<myData> data = new ArrayList<>();
int[] icons = {R.drawable.fullstar,R.drawable.fullstar,R.drawable.fullstar,R.drawable.fullstar};
String[] titles = {"San Francisco","Seattle","Tokyo","Osaka"};
for(int i = 0; i < titles.length && i < icons.length; i++)
{
myData current = new myData();
current.iconId = icons[i];
current.cityName = titles[i];
data.add(current);
}
return data;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
private static class myData
{
private int iconId;
private String cityName;
}
private class CityViewAdapter extends RecyclerView.Adapter<CityViewAdapter.MyViewHolder>
{
private LayoutInflater inflater;
private ArrayList<myData> infoList = new ArrayList<>();
public CityViewAdapter(Context context, ArrayList<myData> data)
{
inflater = LayoutInflater.from(context);
this.infoList = data;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = inflater.inflate(R.layout.fragment_cards_cityview,parent,false);
MyViewHolder holder = new MyViewHolder(view);//special way to avoid "findViewById everytime you make a view
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position)
{
myData current = infoList.get(position);
holder.title.setText(current.cityName);
holder.icon.setImageResource(current.iconId);
}
#Override
public int getItemCount() {
return 0;
}
class MyViewHolder extends RecyclerView.ViewHolder
{
TextView title;
ImageView icon;
public MyViewHolder(View itemView)
{
super(itemView);
title = (TextView) itemView.findViewById(R.id.fragCardsCity_textView);
icon = (ImageView) itemView.findViewById(R.id.fragCardsCity_imageview);
}
}
}
}
I've got a RecyclerView which populates from an ArrayList. The output is a CardView layout.
In the Cardview, there are 2 buttons amongst other Views.
They only have to read the current value of a TextView, which by default is 1, and increase or decrease it.
The Arraylist contains 8 items.
When I run the app the UI works fine. Trouble is when I try to modify the value of the TextView.
The value is correctly increased and decreased on the CardView I'm working on, but ALSO the value is modified on another CardView. And in that second CardView, modifying its TextView value, also modifies the first one.
So, what am I doing wrong?
This is my Fragment:
public class Fragment_rosas extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_rosas,container,false);
RecyclerView recyclerview_rosas;
RecyclerView.Adapter adaptador_rv_rosas;
RecyclerView.LayoutManager lm_rosas;
List rosas = new ArrayList();
rosas.add(new Tropa(1,R.drawable.minibarbaro, getResources().getString(R.string.barbaro),7,1));
recyclerview_rosas = (RecyclerView) view.findViewById(R.id.recyclerView_tropasRosas);
recyclerview_rosas.setHasFixedSize(true);
lm_rosas = new LinearLayoutManager(getContext());
recyclerview_rosas.setLayoutManager(lm_rosas);
adaptador_rv_rosas = new AdaptadorTropa(rosas);
recyclerview_rosas.setAdapter(adaptador_rv_rosas);
return view;
}
}
And here the part of code on my Adapter:
#Override
public void onBindViewHolder(final TropaViewHolder viewHolder, int i) {
viewHolder.imagen.setImageResource(items.get(i).getImagen());
viewHolder.nombre.setText(items.get(i).getNombre());
viewHolder.maxnivel.setText(String.valueOf(items.get(i).getNivelMax()));
viewHolder.espacioencamp.setText((String.valueOf(items.get(i).getEspacioEnCamp())));
final String nombre = items.get(i).getNombre();
final int maxnivel = items.get(i).getNivelMax();
viewHolder.nivelmas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String niveltemp = viewHolder.nivel.getText().toString();
String nivelmaxtemp = viewHolder.maxnivel.getText().toString();
int nivel = Integer.parseInt(niveltemp);
int maxxnivel = Integer.parseInt(nivelmaxtemp);
int nuevonivel = nivel+1 ;
if (nuevonivel<=maxxnivel) {
viewHolder.txtv_nivel.setText(String.valueOf(nuevonivel));
}
}
});
My OnCreateViewHolder (nothing really happens here):
#Override
public TropaViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.cardview, viewGroup, false);
return new TropaViewHolder(v);
}
Here is the solution, as mentioned in the comment above, it addresses two problems:
1. positiontoValueMap - saves current value for each position
2. onclicklistener is passed to the ViewHolder in onCreateViewHolder
Adapter Class
public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List<String> dataList;
private Map<Integer, Integer> positionToValueMap = new HashMap<>();
public MyAdapter(Context context, List<String> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, null, false);
return new MyViewHolder(view, new OnRecyclerItemClickListener());
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MyViewHolder) holder).onRecyclerItemClickListener.updatePosition(position);
((MyViewHolder) holder).position.setText("" + position);
((MyViewHolder) holder).title.setText(dataList.get(position));
int valueToDisplay = 1;
if(positionToValueMap.containsKey(position)) {
valueToDisplay = positionToValueMap.get(position);
} else {
positionToValueMap.put(position, valueToDisplay);
}
((MyViewHolder) holder).valueView.setText("value: " + valueToDisplay);
}
#Override
public int getItemCount() {
return dataList.size();
}
private class MyViewHolder extends RecyclerView.ViewHolder {
private OnRecyclerItemClickListener onRecyclerItemClickListener;
private TextView position;
private TextView title;
private TextView valueView;
public MyViewHolder(View itemView, OnRecyclerItemClickListener onRecyclerItemClickListener) {
super(itemView);
itemView.setOnClickListener(onRecyclerItemClickListener);
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
this.position = (TextView) itemView.findViewById(R.id.position);
this.title = (TextView) itemView.findViewById(R.id.title);
this.valueView = (TextView) itemView.findViewById(R.id.value_view);
}
}
private class OnRecyclerItemClickListener implements View.OnClickListener {
private int position = -1;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
int oldValue = positionToValueMap.get(position); // get current value
oldValue++; // increment
positionToValueMap.put(position, oldValue); // save current value
notifyItemChanged(position); // update clicked view so that it picks up the new saved value from the positionToValueMap in onBindViewHolder
}
}
}
RecyclerView item layout
<TextView
android:id="#+id/position"
android:layout_width="30dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/title"
android:layout_width="50dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_dark"
android:layout_toRightOf="#id/position" />
<TextView
android:id="#+id/value_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_toRightOf="#id/title"
android:layout_alignParentRight="true"/>
</RelativeLayout>
And Activity to test it out
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(new MyAdapter(getApplicationContext(), getSampleData()));
}
private static List<String> getSampleData() {
List<String> dataList = new ArrayList<>();
dataList.add("zero");
dataList.add("one");
dataList.add("two");
dataList.add("three");
dataList.add("four");
dataList.add("five");
dataList.add("six");
dataList.add("seven");
dataList.add("eight");
dataList.add("nine");
dataList.add("ten");
dataList.add("eleven");
dataList.add("twelve");
dataList.add("thirteen");
dataList.add("fourteen");
dataList.add("fifteen");
dataList.add("sixteen");
dataList.add("seventeen");
dataList.add("eighteen");
dataList.add("nineteen");
dataList.add("twenty");
return dataList;
}
}
activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"/>
</RelativeLayout>