Recyclerview is null through whole lifecycle - java

I have a problem that is driving me nuts and been searching several hours around the web but cant find a solution. I want to set an animation on the first view in my recyclerview when I add new data to the list. But I cant because the recyclerview is null.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
orientation = getResources().getConfiguration().orientation;
model = ViewModelProviders.of(getActivity()).get(ViewModelAdvices.class);
model.getAdvices().observe(this, new Observer <List <Advice>>() {
//Update recyclerview automatically when data is changed
#Override
public void onChanged(List <Advice> advices) {
filtered_advices_list.clear();
filtered_advices_list.addAll(advices);
adapter_recycler_view.notifyDataSetChanged();
}
});
}
#Override
public void onResume() {
super.onResume();
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.test_item);
View v = recycler_view.getChildAt(0);
v.startAnimation(animation);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.show_advices_fragment, container, false);
setupLayoutDifferences(view);
recycler_view = (RecyclerView) view.findViewById(R.id.recycler_view);
layout_manager = new LinearLayoutManager(getContext());
recycler_view.setLayoutManager(layout_manager);
adapter_recycler_view = new AdapterRV(filtered_advices_list);
recycler_view.setAdapter(adapter_recycler_view);
spinner_1 = (Spinner) view.findViewById(R.id.spinner_1);
adapter_spinner_1 = ArrayAdapter.createFromResource(view.getContext(), R.array.categories, android.R.layout.simple_spinner_item);
adapter_spinner_1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_1.setAdapter(adapter_spinner_1);
spinner_1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView <?> parent, View view, int position, long id) {
String category = spinner_1.getItemAtPosition(spinner_1.getSelectedItemPosition()).toString();
model.setCategory(category);
}
#Override
public void onNothingSelected(AdapterView <?> parent) { }
});
return view;
}
}
show_advices_fragment
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/colorBlueGreen"
android:paddingBottom="6dp">
<Spinner
android:id="#+id/spinner_1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:backgroundTint="#color/colorBlack" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<Button
android:id="#+id/button_add_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:visibility="gone"
android:text="#string/button_add_activity" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/button_add_activity"
android:background="#color/colorLightGrey"
android:scrollbars="vertical"
/>
</RelativeLayout>
</LinearLayout>
list_item_activity_main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:background="#color/colorWhite"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:weightSum="3">
<TextView
android:id="#+id/text_view_advice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/border"
android:textColor="#color/colorPrimary"
android:paddingRight="4dp"
android:layout_weight="1"
android:text="TextView" />
<TextView
android:id="#+id/text_view_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/colorGrey"
android:layout_weight="2"
android:gravity="center"
android:text="TextView" />
</LinearLayout>
And test_item
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_longAnimTime">
<translate
android:interpolator="#android:anim/decelerate_interpolator"
android:fromXDelta="100%p"
android:toXDelta="0"
/>
<alpha
android:fromAlpha="0.5"
android:toAlpha="1"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
/>
</set>
In the onResume I am in the last lifecycle I suppose and the recyclerview is being build up already in onCreateView. I guess that the build-up of the recyclerview aint finished before I reach onResume, but how can I solve this?
If I do the animation with a mouseclick when the fragment is already loaded it works but not when I switch fragment and the recyclerview is being built up again.

Try this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
orientation = getResources().getConfiguration().orientation;
model = ViewModelProviders.of(getActivity()).get(ViewModelAdvices.class);
model.getAdvices().observe(this, new Observer<List<Advice>>() {
//Update recyclerview automatically when data is changed
#Override
public void onChanged(List<Advice> advices) {
filtered_advices_list.clear();
filtered_advices_list.addAll(advices);
}
});
}
#Override
public void onResume() {
super.onResume();
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.test_item);
View v = recycler_view.getChildAt(0);
v.startAnimation(animation);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.show_advices_fragment, container, false);
setupLayoutDifferences(view);
recycler_view = (RecyclerView) view.findViewById(R.id.recycler_view);
layout_manager = new LinearLayoutManager(getContext());
recycler_view.setLayoutManager(layout_manager);
populateAdapter();
spinner_1 = (Spinner) view.findViewById(R.id.spinner_1);
adapter_spinner_1 = ArrayAdapter.createFromResource(view.getContext(), R.array.categories, android.R.layout.simple_spinner_item);
adapter_spinner_1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_1.setAdapter(adapter_spinner_1);
spinner_1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String category = spinner_1.getItemAtPosition(spinner_1.getSelectedItemPosition()).toString();
model.setCategory(category);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
if (adapter_recycler_view != null){
adapter_recycler_view.notifyDataSetChanged();
}
return view;
}
private void populateAdapter() {
adapter_recycler_view = new AdapterRV(filtered_advices_list);
recycler_view.setAdapter(adapter_recycler_view);
}

You can't depends on onResume() in Fragment, because it's not 100% called after onCreateView() on some Android versions (More details at Fragment onResume() & onPause() is not called on backstack). So, there is a probability that you're fragment layout creation is not yet finished.
You can wait until the RecyclerView is finished inflating all the items with OnGlobalLayoutListener then show the animation for the first item:
recycler_view.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// show the animation
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.test_item);
View v = recycler_view.getChildAt(0);
v.startAnimation(animation);
// remove listener so that this won't be called multiple time.
recycler_view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});

Thank you for trying to help me. Problem is that my application is probably not the best organized so everything runs before my recyclerview is done with the list it gets from ViewModel. But doing the animation on a separate thread works like a charm, then I also have full control over the animation.
if(action.equals("addData")) {
Thread thread = new Thread() {
#Override
public void run() {
try {
boolean recycler_view_loading = true;
while(recycler_view_loading ) {
sleep(250);
if (recycler_view.getChildAt(0) != null) {
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.item_animation_side);
View v = recycler_view.getChildAt(0);
v.startAnimation(animation);
recycler_view_loading = false;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}

Related

How to add Fragment from BaseAdapter

I'm developing an English-Japanese learning app, where it has a stack of cards where users can swipe through, and on each current card, the user can touch the card to flip to the other side of a card, which show the meaning of the word.
For the swipe function, I'm using a library SwipeFlingAdapterView, which support setOnItemClick. Now I need to do the flipping part. I read the tutorial here, which requires 2 fragments to do the flip:
https://developer.android.com/training/animation/cardflip.html
The structure Im setting below:
stack_of_cards_fragment.xml
<FrameLayout 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"
......
>
<com.lorentzos.flingswipe.SwipeFlingAdapterView
android:id="#+id/swipeFlingAdapterViewFront"
android:layout_width="match_parent"
android:layout_height="match_parent"
</com.lorentzos.flingswipe.SwipeFlingAdapterView>
</FrameLayout>
StackOfCardsFragment.java
public class StackOfCardsFragment extends Fragment {
ArrayList<TestModel> cardsList;
Context context;
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.stack_of_cards_fragment,container,false);
final CardsAdapter arrayCardsAdapter;
cardsList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//dump data
TestModel model = new TestModel();
model.isFlipped = false;
cardsList.add(model);
}
SwipeFlingAdapterView flingContainer = ButterKnife.findById(view,R.id.swipeFlingAdapterViewFront);
ButterKnife.bind(this, view);
arrayCardsAdapter = new CardsAdapter(context, cardsList);
flingContainer.setAdapter(arrayCardsAdapter);
flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
#Override
public void removeFirstObjectInAdapter() {
Log.d("LIST", "removed object!");
if(!cardsList.isEmpty())
{arrayCardsAdapter.remove(0);}
}
#Override
public void onLeftCardExit(Object dataObject) {
Log.e("Swipe Direction","Left");
}
#Override
public void onRightCardExit(Object dataObject) {
Log.e("Swipe Direction","Right");
}
#Override
public void onAdapterAboutToEmpty(int itemsInAdapter) {
if(!cardsList.isEmpty()) {
arrayCardsAdapter.notifyDataSetChanged();
Log.d("LIST", "notified");
}else Log.e("Check Empty","Its empty");
}
#Override
public void onScroll(float scrollProgressPercent) {
Log.e("onScroll", "scrollProgressPercent");
}
});
flingContainer.setOnItemClickListener(new SwipeFlingAdapterView.OnItemClickListener() {
#Override
public void onItemClicked(int itemPosition, Object dataObject) {
//This is where I want to change the Front Card Fragment to Back Card Fragment.
}
});
return view;
}
}
and below is the part where I'm struggling to do.
flash_card_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_dark">
<LinearLayout
android:id="#+id/child_fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
CardsAdapter.java
public class CardsAdapter extends BaseAdapter {
Context context;
ArrayList<TestModel> cardsList;
ViewFlipper viewFlipper;
public CardsAdapter(Context context, ArrayList cardsList ) {
this.context = context;
this.cardsList = cardsList;
}
#Override
public int getCount() {
return cardsList.size();
}
#Override
public Object getItem(final int i) {
return cardsList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(final int i, View view, final ViewGroup viewGroup) {
if (view == null) {
LayoutInflater vi = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.flash_card_layout, viewGroup, false);
//This is where I want to set the Front Card Fragment
Fragment frontCardFragment = new EachFrontCardFragment();
FragmentTransaction transaction = ((VocabularyGameActivity) context).getSupportFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.add(R.id.child_fragment_container, frontCardFragment);
transaction.commit();
}
return view;
}
public void remove(int i) {
cardsList.remove(i);
notifyDataSetChanged();
}
}
each_card_front_fragment.xml and one for the each_card_back_fragment.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/cardviewfront">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<TextView android:id="#+id/txtWord_cardfront"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="English"
android:textStyle="bold"
android:textSize="50sp"
android:textColor="#android:color/black"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:layout_marginBottom="50dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
I already created 2 fragments for each_card_front_fragment and each_card_back_fragment.
What am I missing here? All the code above is only showing me the cardAdapter in the StackOfCardsFragment(which is only a background), but the each_card_front_fragment doesn't show up.
I already try set up a BroadcastReceiver from (CardsAdapter)BaseAdapter to send to the VocabulartyActivity to set the each_card_front_fragment there but the same outcome.
is the any other way to set the Fragment in the BaseAdapter?

Adding GridView for TabAcitivty fragments

I am trying to add gridview for my layout.
The MainActivity contains 5 number of tabs , where first tab is AlbumsActivity.
AlbumsActivity
public class AlbumsActivity extends Fragment{
public AlbumsActivity() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.activity_albums, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
GridView gridView = (GridView) findViewById(R.id.grid_view);
// Instance of ImageAdapter Class
gridView.setAdapter(new ImageAdapter(this));
}
}
ImageAdapter.java
I am using this class adapter to populate the grids in AlbumsActivity.
public class ImageAdapter extends BaseAdapter {
private Context mContext;
// Keep all Images in array
public Integer[] mThumbIds = {
R.drawable.splas,
R.drawable.abc,
};
// Constructor
public ImageAdapter(Context c){
mContext = c;
}
#Override
public int getCount() {
return mThumbIds.length;
}
#Override
public Object getItem(int position) {
return mThumbIds[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(mThumbIds[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
return imageView;
}
}
grid_layout.xml
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="3"
android:columnWidth="90dp"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:gravity="center"
android:stretchMode="columnWidth" >
</GridView>
activity_albums.xml
This is layout file for AlbumsActivity , where i want to show grids in page.
<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:padding="16dp"
android:orientation="vertical"
tools:context="com.example.android.musiclist.AlbumsActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/ald"
android:textSize="20sp"
android:textColor="#color/colorPrimaryDark"
android:textStyle="bold"/>
</LinearLayout>
I think you are doing it wrong.
MainActivity - 5 Tabs and one framelayout
AlbumsActivity (Fragment) - Activity_Albums.xml (TextView, GridView)
ImageAdapter (BaseAdapter) - Custom Layout (ImageView)
3 -> 2 (Gridview) -> 1
if not you have to create, set parameters and inject gridview with custom layout to main layout programatically
//Try this
activity_albums.xml
<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:padding="16dp"
android:orientation="vertical"
tools:context="com.example.android.musiclist.AlbumsActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/ald"
android:textSize="20sp"
android:textColor="#color/colorPrimaryDark"
android:textStyle="bold"/>
<FrameLayout
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
AlbumsActivity
public class AlbumsActivity extends Fragment{
private View view;
private FrameLayout fl;
private GridView gv;
public AlbumsActivity() {
// 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.activity_albums,container,false);
fl = view.findViewById(R.id.frameLayout);
gv = findViewById(R.id.grid_view);
gv.setAdapter(new ImageAdapter(this));
fl.addView(gv);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Or Something similar, I am too lazy to type everything now. just google search "android custom arrayadapter" and you will find tons of examples. It's really simple

RecyclerView not calling getItemCount

I've investigated several SO answers on this question (here, here, and here) and none of the proposed solutions have worked. My problem is that my RecyclerView list items aren't being displayed. I've set breakpoints in MessengerRecyclerAdapter, onCreateViewHolder, onBindViewHolder, and getItemCount and only the first one is ever called. While in a breakpoint I've entered the expression evaluator and executed
MessengerRecyclerAdapter.getItemCount();
And received the expected answer of 20. The RecyclerView itself takes up the intended content area as demonstrated by the screenshot below (I turned the RecyclerView magenta to highlight the space it occupies).
My RecyclerView XML code is below:
<?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.support.v7.widget.RecyclerView
android:id="#+id/thread_list"
android:background="#color/colorAccent"
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:name="com.jypsee.jypseeconnect.orgPicker.MessengerListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
tools:context="com.jypsee.jypseeconnect.orgPicker.MessengerListFragment"
tools:listitem="#layout/fragment_messenger_cell"/>
</LinearLayout>
My RecyclerView Cell XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#color/blueText"/>
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#color/darkText"/>
</LinearLayout>
My ListFragment class:
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
List<DummyContent.DummyItem> items = new ArrayList<>();
for (Integer i = 0; i<20; i++){
DummyContent.DummyItem item = new DummyContent.DummyItem(i.toString(),"Content","Details");
items.add(item);
}
View view = inflater.inflate(R.layout.fragment_messenger_list, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.thread_list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerAdapter = new MessengerThreadRecyclerAdapter(items, mListener);
mRecyclerView.setAdapter(mRecyclerAdapter);
mRecyclerAdapter.notifyDataSetChanged();
return view;
}
My Adapter class:
public class MessengerRecyclerAdapter
extends RecyclerView.Adapter<MessengerRecyclerAdapter.MessageThreadHolder>{
private final List<DummyItem> mValues;
private final RecyclerViewClickListener mListener;
public MessengerRecyclerAdapter(List<DummyItem> items, RecyclerViewClickListener listener) {
mValues = items;
mListener = listener;
}
#Override
public MessageThreadHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_messenger_cell, parent, false);
return new MessageThreadHolder(view);
}
#Override
public void onBindViewHolder(final MessageThreadHolder holder, final int position) {
holder.mItem = mValues.get(position);
holder.mIdView.setText(mValues.get(position).id);
holder.mContentView.setText(mValues.get(position).content);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
mListener.recyclerViewListClicked(v, position);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class MessageThreadHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final TextView mContentView;
public DummyItem mItem;
public MessageThreadHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content);
}
}
}
As you can see I've set the linearLayout orientation to vertical and set the layout manager, which were the 2 most common solutions. I'm really at a loss as to what to try next, so any help is appreciated.
As I said in previous Answer edit. The issues was in your xml. The main reason it was not showing was because, You were trying to add the fragment using include tag instead of fragment tag thus respective fragment class was never getting called on the fragment layout being added to your activity.
Below is the code you needed to add the Fragment correctly.
<fragment
android:id="#+id/message_thread"
android:name="com.jypsee.jypseeconnect.orgPicker.MessengerThreadListFragment"
layout="#layout/fragment_messengerthread_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_messengerthread_list" />
And your fragment layout should be like this
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".orgPicker.MessengerThreadListFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/thread_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Here is the screenshot of working
In my case , I was missing calling notifyDataSetChanged() after setting list in adapter.

Why is my RecyclerView not showing anything? / What happend if Recycler Adapter is set again after notifyDataSetChanged() called?

I am new to Android Programming and I've been trying to make a fragment which displays a list of items using RecyclerView. Everything seems fine and there is no error when I run the app.
Here is my code:
FriendsFragment.java
public class FriendsFragment extends android.support.v4.app.Fragment {
#Bind(R.id.friendList)
RecyclerView friendList;
RecyclerView.LayoutManager friendsManager;
FriendListAdapter friendListAdapter;
public FriendsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_friends, container, false);
ButterKnife.bind(this, view);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
friendList.setHasFixedSize(true);
friendsManager = new LinearLayoutManager(view.getContext());
friendList.setLayoutManager(friendsManager);
friendListAdapter = new FriendListAdapter(new ArrayList<Friends>());
friendList.setAdapter(friendListAdapter);
test();
friendListAdapter.notifyDataSetChanged();
friendList.setAdapter(friendListAdapter);
super.onViewCreated(view, savedInstanceState);
}
private void test() {
Friends friend = new Friends();
friend.setName("Junjie Saitamaria");
friendListAdapter.addNewFriend(friend);
}
}
FriendListAdapter.java
public class FriendListAdapter extends RecyclerView.Adapter<FriendListAdapter.ViewHolderFriend> {
private List<Friends> friendList;
public FriendListAdapter(List<Friends> friends) {
if(friends != null) {
friendList = friends;
}
}
public void addNewFriend(Friends friend) {
friendList.add(0, friend);
}
#Override
public ViewHolderFriend onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_friend, parent, false);
ViewHolderFriend viewHolder = new ViewHolderFriend(view);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolderFriend holder, int position) {
Friends currentFriend = friendList.get(position);
holder.friendName.setText(currentFriend.getName());
}
#Override
public int getItemCount() {
return friendList.size();
}
static class ViewHolderFriend extends RecyclerView.ViewHolder {
#Bind(R.id.friend_avatar)
public ImageView friendThumbnail;
#Bind(R.id.friend_name)
public TextView friendName;
Context currentContext = null;
public ViewHolderFriend(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
this.currentContext = itemView.getContext();
}
}
}
fragment_friends.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"
android:layout_margin="10dp"
tools:context="com.cebuinstituteoftechnology_university.citumessenger.FriendsFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/friendList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true" >
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
list_item_friend.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:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="80dp"
android:id="#+id/friends_card"
android:elevation="2dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- icon -->
<ImageView
android:id="#+id/friend_avatar"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:contentDescription="icon"
android:src="#drawable/avatar"
/>
<!-- title -->
<TextView
android:id="#+id/friend_name"
android:layout_width= "wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_toRightOf="#+id/friend_avatar"
android:layout_alignBaseline="#+id/friend_avatar"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="Name" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Looks everything fine except this extra line friendList.setAdapter(friendListAdapter); in below code:
friendList.setAdapter(friendListAdapter);
test();
friendListAdapter.notifyDataSetChanged();
friendList.setAdapter(friendListAdapter);
Replace above 3 lines with this and see :
friendList.setAdapter(friendListAdapter);
test();
friendListAdapter.notifyDataSetChanged();
Remove following line from onViewCreated() Method
friendList.setAdapter(friendListAdapter);
other code is fine.

How to replace fragment run time

I want to add and replace Frame layout with fragment on fragment-1 and fragment-2 on item click of Grid and List item.
I had created main.xml class
<?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="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="fill_parent" >
<fragment
android:id="#+id/fragment1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
class="com.example.fragment.Fragment1" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#000000" />
<fragment
android:id="#+id/fragment2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
class="com.example.fragment.Fragment2" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="fill_parent"
android:background="#000000" />
<FrameLayout
android:id="#+id/fragment3"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="2"/>
Here is my fragment_1.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:orientation="vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp" >
<GridView
android:id="#+id/Grid1"
android:layout_width="match_parent"
android:numColumns="auto_fit"
android:columnWidth="100dp"
android:layout_height="0dp"
android:layout_weight="1"
android:drawSelectorOnTop="false" />
and here is my row_fragment1_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="15dp"
android:orientation="vertical" >
<ImageView
android:id="#+id/img_view"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#CCCCCC"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp" />
and fragment_3.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:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/tv_fragment3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="22sp"
android:gravity="center"
android:text="This is 3rd Fragment" />
and here is my Main.xml
public class Main extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
and here is Fragment1.class
public class Fragment1 extends Fragment implements OnItemClickListener
{
Activity myActivity;
GridView mGridView;
private String ListItem[] = {"Item 1","Item 2","Item 3","Item 4","Item 5","Item 6","Item 7"};
private int imgID[] = {R.drawable.admin_access_rule,
R.drawable.admin_backup,R.drawable.admin_browsesite,
R.drawable.admin_comment_post,R.drawable.admin_content,
R.drawable.admin_content_type,R.drawable.admin_logout,};
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
this.myActivity = activity;
Toast.makeText(activity.getApplicationContext(), "On Attach", Toast.LENGTH_SHORT).show();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Toast.makeText(myActivity.getApplicationContext(), "On Create", Toast.LENGTH_SHORT).show();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Toast.makeText(myActivity.getApplicationContext(), "On Create View", Toast.LENGTH_SHORT).show();
View view = inflater.inflate(R.layout.fragment_1,container, false);
mGridView = (GridView)view.findViewById(R.id.Grid1);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
Toast.makeText(myActivity.getApplicationContext(), "On Activity Created", Toast.LENGTH_SHORT).show();
super.onActivityCreated(savedInstanceState);
}
#Override
public void onStart()
{
super.onStart();
mGridView.setAdapter(new GridBaseAdapter(myActivity));
mGridView.setOnItemClickListener(this);
}
private class GridBaseAdapter extends BaseAdapter
{
LayoutInflater mLayoutInflater = null;
public GridBaseAdapter(Context mContext)
{
mContext = myActivity;
mLayoutInflater = LayoutInflater.from(mContext);
}
#Override
public int getCount()
{
return ListItem.length;
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position)
{
return ListItem.length;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
if(convertView == null)
{
convertView = mLayoutInflater.inflate(R.layout.row_fragment_list, null);
}
ImageView mImageView = (ImageView) convertView.findViewById(R.id.img_view);
mImageView.setImageResource(imgID[position]);
TextView tvUserEmail = (TextView) convertView.findViewById(R.id.text2);
tvUserEmail.setText("Sub " +ListItem[position]);
return convertView;
}
}
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long id)
{
TextView txt3 = (TextView)myActivity.findViewById(R.id.tv_fragment3);
txt3.setText("1st Fragment's : " + position +" Item Clicked");
}
}
My Fragment2.class
public class Fragment2 extends ListFragment
{
Activity myActivity;
private String ListItem[] = {"Item 1","Item 2","Item 3","Item 4","Item 5","Item 6","Item 6","Item 7"};
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
this.myActivity = activity;
Toast.makeText(activity.getApplicationContext(), "On Attach", Toast.LENGTH_SHORT).show();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Toast.makeText(myActivity.getApplicationContext(), "On Create", Toast.LENGTH_SHORT).show();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Toast.makeText(myActivity.getApplicationContext(), "On Create View", Toast.LENGTH_SHORT).show();
/** Creating an array adapter to store the list of countries **/
ArrayAdapter<String> adapter = new ArrayAdapter<String>(inflater.getContext(), android.R.layout.simple_list_item_1,ListItem);
/** Setting the list adapter for the ListFragment */
setListAdapter(adapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
Toast.makeText(myActivity.getApplicationContext(), "On Activity Created", Toast.LENGTH_SHORT).show();
super.onActivityCreated(savedInstanceState);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id)
{
Toast.makeText(myActivity.getApplicationContext(), position +" Item Clicked", Toast.LENGTH_SHORT).show();
TextView txt3 = (TextView)myActivity.findViewById(R.id.tv_fragment3);
txt3.setText("2nd Fragment's : " + position +" Item Clicked");
super.onListItemClick(l, v, position, id);
}
}
And Last my Fragment3.class
public class Fragment3 extends Fragment
{
Activity myActivity;
TextView txt_view;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
this.myActivity = activity;
Toast.makeText(activity.getApplicationContext(), "On Attach", Toast.LENGTH_SHORT).show();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Toast.makeText(myActivity.getApplicationContext(), "On Create", Toast.LENGTH_SHORT).show();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Toast.makeText(myActivity.getApplicationContext(), "On Create View", Toast.LENGTH_SHORT).show();
View view = inflater.inflate(R.layout.fragment_3,container, false);
txt_view = (TextView)view.findViewById(R.id.tv_fragment3);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
Toast.makeText(myActivity.getApplicationContext(), "On Activity Created", Toast.LENGTH_SHORT).show();
super.onActivityCreated(savedInstanceState);
}
}
Make fragments expose interface that your activity can attach itself to. The event should occur when desired (e.g. list item is clicked). Then, activity should place instance of the fragment where it should be, for example:
// fragment is an instance of the fragment you want to show
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment3, fragment);
transaction.commit();

Categories