I followed the recyclerview guidelines and built one for the app I am making, but it does not scroll to the bottom for some reason. I compared it with google code snippets, as well as other code snippets online and can't see the difference. I have posted a picture and the code I am using. I am using tabs, therefore the recyclerview is populated in a fragment.
What the app looks like:
http://imgur.com/H5uOLFR
the adapter class:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Group> groups;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView groupName;
public TextView groupDate;
public TextView groupLocation;
public TextView className;
public ViewHolder(View v) {
super(v);
groupName = (TextView) v.findViewById(R.id.groupName);
groupDate = (TextView) v.findViewById(R.id.groupDate);
groupLocation = (TextView) v.findViewById(R.id.groupLocation);
className = (TextView) v.findViewById(R.id.className);
}
}
/*
* TODO: finish this method
*/
public void add(int position, String item) {
notifyItemInserted(position);
}
public void remove(String item) {
int position = groups.indexOf(item);
groups.remove(position);
notifyItemRemoved(position);
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Group> groupsList) {
groups = groupsList;
Log.d("TEST", "Number of Groups: " +
Integer.toString(groups.size()));
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.group_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final Group group = groups.get(position);
// holder.groupName.setText(group.getName());
holder.groupName.setText(group.getName());
holder.groupDate.setText(group.getFormattedDate());
holder.groupLocation.setText(group.getLocation());
holder.className.setText(group.getParent().getName());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return groups.size();
}
}
The Fragment class:
public class groupsFragment extends Fragment implements GroupLeaver, GroupRetriever {
private RecyclerView rv;
private List<Group> groups;
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
Log.d("TEST", "Entered onCreate");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AppMain.getController().retrieveGroups(groupsFragment.this);
Log.d("TEST", "Entered onCreateView");
View rootView = inflater.inflate(R.layout.groups_fragment, container, false);
rv = (RecyclerView) rootView.findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
Log.d("TEST", "Size of LIST: " + Integer.toString(groups.size()));
MyAdapter adapter = new MyAdapter(groups);
rv.setAdapter(adapter);
return rootView;
}
#Override
public void onMyGroupsFound(List<Group> groups) {
Log.d("TEST", "Entered onMyGroupsFound");
Logg.info(this.getClass(), "Found %d groups for member %s", groups.size(), User.getCurrentUser().getDisplayName());
this.groups = groups;
}
#Override
public void onGroupLeft(Group oldGroup) {
}
#Override
public void onGroupLeftFailed(Group group, ParseException e) {
}
}
The xml layout for the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null"/>
</FrameLayout>
The xml layout for the recyclerview items:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="horizontal">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="3"
android:orientation="vertical">
<TextView
android:id="#+id/groupName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Name"
/>
<TextView
android:id="#+id/groupDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Date"
/>
<TextView
android:id="#+id/groupLocation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Group Location"
/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/className"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="right"
android:text="Class Name"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
You can use these lines to scroll recyclerview to:
list.add(0, group);
adapter.notifyItemInserted(0);
recyclerview.scrollToPosition(0);
Thanks to everyone who responded, but turns out the problem was the version of RecyclerView I was compiling.
Previously I was compiling this
compile 'com.android.support:recyclerview-v7:22.0.0'
But I changed it to this and it worked
compile 'com.android.support:recyclerview-v7:22.2.0'
Credits to #roi divon for the answer: CoordinatorLayout with RecyclerView & CollapsingToolbarLayout
Maybe adding these lines to the recyclerView will do:
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
This is my recyclerView which is working:
<android.support.v7.widget.RecyclerView
android:id="#+id/menuRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"/>
I am not sure but I think problem might be Framelayout You can try with Linearlayout instead of Framelayout in your xml layout for the recyclerview items
Related
I want to build a complex layout using recyclerview android. In the layout, I want to have a camera button to the top left fixed and a recyclerview wrapped around it with gallery images. I have checked flexbox layout manager for recyclerview but it doesn't seem to match my use-case.
I want the header to be non-repeating and not to scroll with other items vertically. Here's the layout for the header:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/shareLayout"
android:layout_width="185dp"
android:layout_height="135dp"
android:layout_below="#id/trendingToolbar"
android:background="#color/black">
<ImageView
android:id="#+id/cameraShareIV"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
app:srcCompat="#drawable/camera_white" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/cameraShareIV"
android:layout_centerHorizontal="true">
<TextView
android:id="#+id/infoTxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginLeft="20dp"
android:gravity="center_horizontal"
android:text="#string/share_pic_video"
android:textColor="#android:color/white"
android:textSize="13sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/infoTxt"
android:layout_marginLeft="16dp"
android:text="#string/share_timeout_txt"
android:textColor="#color/colorPrimaryDark"
android:textSize="11sp"
android:textStyle="bold" />
</RelativeLayout>
and in my activity, here's the XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="base.android.com.thumbsapp.UI.Fragments.TrendingFragment">
<include layout="#layout/trending_toolbar"
android:id="#+id/trendingToolbar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/trendingRV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/trendingToolbar"/>
Previously, I had the header inside the activity XML but had no way to wrap a recyclerview around it. So, I have decide to use an adapter like below:
public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = TrendingAdapter.class.getSimpleName();
private Context context;
private List<Trending> itemList;
private static final int HEADER = 0;
private static final int ITEMS = 1;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
switch (viewType){
case HEADER:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_header, parent, false);
return new TrendingHeaderViewHolder(v);
case ITEMS:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_items_layout, parent, false);
return new TrendingItemsViewHolder(v);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Trending tr = itemList.get(position);
if (holder instanceof TrendingHeaderViewHolder){
((TrendingHeaderViewHolder) holder).cameraShareIV.setOnClickListener( view -> {
// TODO: 4/2/2018 select image from gallery
});
} else if (holder instanceof TrendingItemsViewHolder){
// TODO: 4/2/2018 populate gallery items here with picasso
}
}
#Override
public int getItemCount() {
return itemList.size();
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
I'm confused how to make the header stick and also what to do for getItemViewType method.
Is this the right way to approach this?
Can anyone help out? Thanks.
For this lay out i suggest better option is use this header view
https://github.com/edubarr/header-decor
To make things simple i suggest you to look into this library
In your XML Place RecylerView into StickyHeaderView,choose horizontal or vertical orientation for your RecylerView
<tellh.com.stickyheaderview_rv.StickyHeaderView
android:id="#+id/stickyHeaderView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:scrollbars="vertical" />
</tellh.com.stickyheaderview_rv.StickyHeaderView>
Create data bean class for each item type in RecyclerView. They should extend DataBean. Override the method
public boolean shouldSticky() to decide whether the item view should be suspended on the top.
public class User extends DataBean {
private String login;
private int id;
private String avatar_url;
private boolean shouldSticky;
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.item_user;
}
public void setShouldSticky(boolean shouldSticky) {
this.shouldSticky = shouldSticky;
}
// Decide whether the item view should be suspended on the top.
#Override
public boolean shouldSticky() {
return shouldSticky;
}
}
public class ItemHeader extends DataBean {
private String prefix;
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.header;
}
#Override
public boolean shouldSticky() {
return true;
}
}
Create ViewBinder to bind different type views with specific data beans. As you see, provideViewHolder(View itemView) corresponds for onCreateViewHolder in RecyclerView, and bindView corresponds for onBindViewHolder in RecyclerView.
public class ItemHeaderViewBinder extends ViewBinder<ItemHeader, ItemHeaderViewBinder.ViewHolder> {
#Override
public ViewHolder provideViewHolder(View itemView) {
return new ViewHolder(itemView);
}
#Override
public void bindView(StickyHeaderViewAdapter adapter, ViewHolder holder, int position, ItemHeader entity) {
holder.tvPrefix.setText(entity.getPrefix());
}
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.header;
}
static class ViewHolder extends ViewBinder.ViewHolder {
TextView tvPrefix;
public ViewHolder(View rootView) {
super(rootView);
this.tvPrefix = (TextView) rootView.findViewById(R.id.tv_prefix);
}
}
}
Instantiate StickyHeaderViewAdapter for RecyclerView and register ViewBinders for each item types.
rv = (RecyclerView) findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
List<DataBean> userList = new ArrayList<>();
adapter = new StickyHeaderViewAdapter(userList)
.RegisterItemType(new UserItemViewBinder())
.RegisterItemType(new ItemHeaderViewBinder());
rv.setAdapter(adapter);
I am trying to pick up a single card element kept inside a recycler view and listen to the click and long click events.
However, since you can set the setOnClickListener only on the view, I am finding it difficult to isolate a particular element(card) from the view. As a result, the click event is happening all across the area of the layout.
Please help me isolate a single card from the entire cardview layout and help me write click events to it.
HERE IS MY CODE
CustomAdapter.java
public class CardAdapterLib
extends RecyclerView.Adapter<CardAdapterLib.LibHolder> {
private ArrayList<LibModel> libModel;
public CardAdapterLib(ArrayList<LibModel> data){
this.libModel = data;
}
#Override
public LibHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.recycle_items,parent,false);
// TODO: figure out how to isolate that view
//The listner I have written is getting applied to
the entire layout of R.layout.recycle_items
view.setOnClickListener(LibFragment.myOnClickListener);
return new LibHolder(view);
}
}
My Fragment Class the hosts the recycler view
public class LibFragment extends Fragment {
private static RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private static RecyclerView recyclerView;
private static ArrayList<LibModel> data;
public static View.OnClickListener myOnClickListener;
private static ArrayList<Integer> removedItems;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate
(R.layout.fragment_lib_frgment,container,false);
final CoordinatorLayout LibCoordinatorLayout =
(CoordinatorLayout)view.findViewById(R.id.Lib_coordinatorLayout);
myOnClickListener = new MyOnClickListener(getContext());
recyclerView = (RecyclerView) view.findViewById(R.id.library_rv);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
data = new ArrayList<LibModel>();
for (int i = 0; i < myData.titles.length; i++) {
data.add(new LibModel(myData.titles[i],
myData.authors[i],myData.lang[i],myData.id_[i]));
}
removedItems = new ArrayList<Integer>();
adapter = new CardAdapterLib(data);
recyclerView.setAdapter(adapter);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(getActivity(), recyclerView ,
new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position)
{Toast.makeText(getActivity(),
"SoftPress",Toast.LENGTH_SHORT).show();
// Launch the Requests Fragment here
}
#Override
public void onLongItemClick(View view, int position) {
Toast.makeText(getActivity(),"Hard Press",Toast.LENGTH_SHORT).show();
//Launch the Delete Fragment here
}
})
);
return view;
}
private static class MyOnClickListener implements View.OnClickListener {
private final Context context ;
private MyOnClickListener(Context context) {
this.context = context;
}
#Override
public void onClick(View v) {
// This Toast happens wherever
I click on the R.layout.fragment_lib_frgment area.
// I want to make it happen only when a single card is clicked!
Toast.makeText(context,"Clicked here DA",Toast.LENGTH_SHORT).show();
removeItem(v);
}
private void removeItem(View v) {
int selectedItemPosition = recyclerView.getChildPosition(v);
RecyclerView.ViewHolder viewHolder
= recyclerView.findViewHolderForPosition
(selectedItemPosition);
TextView =(TextView)viewHolder.itemView.
findViewById(R.id.title_card);
String selectedName = (String) titleTV.getText();
int selectedItemId = -1;
for (int i = 0; i < myData.titles.length; i++) {
if (selectedName.equals(myData.titles[i])) {
selectedItemId = myData.id_[i];
}
}
removedItems.add(selectedItemId);
data.remove(selectedItemPosition);
adapter.notifyItemRemoved(selectedItemPosition);
}
}
}
My Layout Files
<?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:tag="cards main container">
<android.support.v7.widget.CardView
xmlns:card_view="https://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/card_view"
android:layout_margin="5dp"
card_view:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="6">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:layout_weight="1"
android:id="#+id/lib_counter"
android:textSize="120px"
android:padding="10dp"
android:layout_centerInParent="true"
android:gravity="center" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="4"
android:id="#+id/details_holder">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/title_card"
android:layout_margin="5dp"
android:text="Title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/author_card"
android:layout_margin="5dp"
android:text="Author"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/lang_card"
android:layout_margin="5dp"
android:text="Language"/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
And for the Fragment
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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:id="#+id/Lib_coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ch330232.pager.Activities.MainActivity">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rvRl"
android:layout_gravity="center_horizontal"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/library_rv"
android:scrollbars="vertical" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
You can separate both clicks in your recycleView Adapter with separating Click listeners for both views as below:
#Override
public YourViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.w("Test", "Parent clicked");
}
});
return new YourViewHolder(itemView);
}
#Override
public void onBindViewHolder(YourViewHolder viewHolder, int i) {
viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.w("Test", "Checkbox clicked");
}
});
}
It is happening every time you click on the fragment because you set it as a click listener for each adapter (or card view) your recycler view has. Use the RecyclerView.addOnItemTouchListener() to activate single items click. Don't add a click listener to every view inside the onBindView method.
currently i am working on a android project.
where i have two String[], now i want to display the data of bothe String[] on my activity.but with my code i am only able to display the data of one String[].
plz check my code.
file name:MyAdapter4.java
public class MyAdapter4 extends RecyclerView.Adapter<MyAdapter4.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView cardview4;
public EditText edit4;
public TextView title4;
public MyViewHolder(View v) {
super(v);
cardview4=(CardView) v.findViewById(R.id.card_view4);
edit4=(EditText) v.findViewById(R.id.otherEdit);
title4=(TextView) v.findViewById(R.id.otherTitle);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter4(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter4.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.other_file_layout, parent, false);
// set the view's size, margins, paddings and layout parameters
MyAdapter4.MyViewHolder vh = new MyAdapter4.MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyAdapter4.MyViewHolder holder, int position) {
holder.title4.setText(mDataset[position]);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
with this code i am only able to display Textview.... but editText is not showing data
and this is the code which i used to attach the adapter
public class FourFragment extends Fragment {
public static String[] arrayOtherTitle, arrayOtherData;
public FourFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_four, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view4);
rv.setHasFixedSize(true);
MyAdapter2 adapter = new MyAdapter2(arrayOtherTitle);
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
The layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:elevation="4dp"
android:id="#+id/card_view4"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:textStyle="bold"
android:layout_weight="1"
android:id="#+id/otherTitle"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/copy"
android:layout_margin="4dp"/>
</LinearLayout>
<EditText
android:layout_width="match_parent"
android:id="#+id/otherEdit"
android:enabled="false"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
As you can see,
1)in my layout file, there are one textview and one edittext.
2)and in the class, FourFragment.java there are two String[] arrayOtherTitle, and arrayOtherData.
3)so, i want to display them on my activity.
where textview will contain data of arrayOtherTitle,
and editext will contain data of arrayOtherData.
but according to my code, currently i am only able to display data of arrayOtherTitle on textview.
and i am new in this topic,plz anyone help me to display the other arrayOtherData data on edittext.
please
i want to reuse an inflated view just the same way a listView adapter does with convertView. Ive been lurking on the source code of adapters with no luck.
I need to add dinamically views depending on data to a recyclerItemView, now im inflating as much times as i need the view but having in mind its inside a recyclerView, this operation could become absurdly costly depending on the amount of data and scrolling behaviour of the user.
Other solution to my problem would be to create a listview inside the recyclerItem, so the listview wouldnt be scrollable, expands to maximum height depending on data added dynamically(making the listview container to expand to show all its data) and make the recyclerItem expand depending on its height.
ACTIVITY
public class Main1Activity extends AppCompatActivity {
RecyclerView recyclerView;
CustomAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
recyclerView = (RecyclerView) findViewById(R.id.recycler);
setUpRecycler();
}
private void setUpRecycler(){
Sample sample1 = new Sample("List of Items1");
Sample sample2 = new Sample("List of Items2");
Sample sample3 = new Sample("List of Items3");
List<Sample> sampleList = new ArrayList<>();
sampleList.add(sample1);
sampleList.add(sample2);
sampleList.add(sample3);
adapter = new CustomAdapter(this,sampleList);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
<?xml version="1.0" encoding="utf-8"?>
<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:padding="30dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
MODEL
public class Sample {
String name;
public Sample(){}
public Sample(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
XML ITEMS
**item_list**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="40dp">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
**item_smaple**
<?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">
<TextView
android:id="#+id/name"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="List of Items"
android:textSize="20sp"/>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:orientation="vertical"/>
</LinearLayout>
ADAPTER
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private List<Sample> mySamples;
private Context mContext;
public CustomAdapter(Context context, List<Sample> mySamples) {
this.mContext = context;
this.mySamples = mySamples;
}
private Context getContext() {
return mContext;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
linearLayout = (LinearLayout) itemView.findViewById(R.id.linearLayout);
}
}
#Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View contactView = inflater.inflate(R.layout.item_sample, parent, false);
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
Sample sample = mySamples.get(position);
holder.name.setText(sample.getName());
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.item_list, null, false);
for (int i = 0; i < 20; i++){
TextView textView = (TextView) v.findViewById(R.id.textView);
textView.setText("hello"+i);
holder.linearLayout.addView(v);
}
}
#Override
public int getItemCount() {
return mySamples.size();
}
}
Right now i´m inflating inside the loop. How could i modify view parameters to make it reusable to the framework?
My app crashes on the addView()
-->java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
The issue that you are referring to is the one which was addressed by creating RecyclerView which is an upgrade to ListView. What RecyclerView does is that it will create/inflate say 5-10 list item and when the user starts scrolling new listItem view(s) are not inflated infact just the data is updated inside the listItem.
This is a great explainer video of how recycler view actually works with a bit of code as well. https://www.youtube.com/watch?v=Wq2o4EbM74k
I hope this clears your doubt regarding the inflation issue.
My app crashes on the addView() -->java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
try:
#Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
Sample sample = mySamples.get(position);
holder.name.setText(sample.getName());
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context
.LAYOUT_INFLATER_SERVICE);
for (int i = 0; i < 20; i++) {
View v = inflater.inflate(R.layout.item_list, holder.linearLayout, false);
TextView textView = (TextView) v.findViewById(R.id.textView);
textView.setText("hello" + i);
holder.linearLayout.addView(v);
}
}
itemSample.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:orientation="vertical">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="List of Items"
android:textSize="20sp"/>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginLeft="30dp"
android:orientation="vertical"
android:isScrollContainer="true"
/>
</LinearLayout>
itemList.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="40dp"
android:isScrollContainer="true"
android:id="#+id/txt_cont"
>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
You should try answer #
I am having problems displaying all the items in my recyclerview. My code only shows one item (Home. I have 3 items: Home, Browse Photos and My Travels)
fragment_navigation_drawer.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_navigation_drawer"
android:background="#EEE"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.traveldiaries.ztir.traveldiaries.NavigationDrawerFragment">
<!-- TODO: Update blank fragment layout -->
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="220dp"
android:background="#16a085"
android:id="#+id/linearLayout">
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/drawerList"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private LayoutInflater inflater;
List<MenuList> data = Collections.emptyList();
public RecyclerAdapter(Context context, List<MenuList> data){
inflater= LayoutInflater.from(context);
this.data = data;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=inflater.inflate(R.layout.itemlist,parent,false);
MyViewHolder holder= new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MenuList current=data.get(position);
holder.title.setText(current.title);
holder.image.setImageResource(current.icon);
}
#Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView title;
ImageView image;
public MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.item_list);
image = (ImageView) itemView.findViewById(R.id.icons);
}
}
}
NavigationDrawerFragment.java (posted code only related to recyclerview)
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);
adapter = new RecyclerAdapter(getActivity(),getData());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return layout;
}
public static List<MenuList> getData(){
List<MenuList> data = new ArrayList<>();
String[] titles={"Home","My Travels","Browse Photos"};
int[] icons ={R.drawable.home,R.drawable.sunglasses,R.drawable.tooltip_image};
for(int i=0;i<3;i++){
MenuList current = new MenuList();
current.title=titles[i];
current.icon=icons[i];
Log.d("Data",titles[i]);
Log.d("Data",""+icons[i]);
data.add(current);
}
return data;
}
itemlist.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">
<ImageView
android:padding="8dp"
android:id="#+id/icons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_menu_camera"
android:layout_gravity="center_vertical"
/>
<TextView
android:id="#+id/item_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dummy Text"
android:layout_gravity="center_vertical"
android:padding="8dp"
/>
</LinearLayout>
What I was able to do is to check all the passed data (all seems to be fine). Also tried to change width to wrap content (fragment_navigation_drawer.xml) in both my relative and linear layout but I just lose my background color instead and still only one item appear.
Change height of LinearLayout to wrap_content in itemlist.xml
android:layout_height="wrap_content"
Just change the height of your itemlist from "match_parent" to "wrap_content".