View Pager is empty only at first time - android

I have a fragment that contains recycle view and on every item press another fragment is shown that holding a view pager that shows fragment on every swipe. when I first enter to the fragment after pressing the recycle view item the pager is not visible.
on second time and the rest of the times the data is shown as expected.
code:
main fragment holds view pager:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/lineItems"
style="#style/TitleTextView"/>
<android.support.v4.view.ViewPager
android:id="#+id/CardTablepager"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content"/>
</LinearLayout>
content fragment (view pager swipes this fragment) :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/poMainlayout">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/CardViewStyle"
android:layout_margin="8dp"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/poLineItemsTable"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarStyle="outsideInset"
/>
</android.support.v7.widget.CardView>
</LinearLayout>
I read few posts with no help: Android Viewpager display wrong data on first load
I also tried to invalidate the adapter from the main fragment with no help:
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager.getAdapter().notifyDataSetChanged();
}
any ideas?

Just notify your adapter onCreateView not onViewCreated
#Override
public void onCreateView(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager.getAdapter().notifyDataSetChanged();
}

Try below changes to your viewpager,
<android.support.v4.view.ViewPager
android:id="#+id/CardTablepager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="600dp"
android:layout_weight="1"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
And for RecyclerView set following properties:
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);

Related

How to put EditText and Send Button in Fragment's Recyclerview?

I have an activity with three Fragments. Is there a way to add Chat functionality on one of Fragments. Details mentioned below. Let me know if anything else is required.
XML file of the activity is listed below.
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
.........
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
......
</android.support.design.widget.CoordinatorLayout>
Fragment's XML for inflating RecyclerView is listed below:-
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/messageList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:layout_below ="#id/appbar"
>
</android.support.v7.widget.RecyclerView>
My two Fragments are working fine. For third Fragment, I have attached adapter for listing chat message which is working fine however I am unable to attach Edittext and send button for chat functionality which I believed shall be outside adapter but inside Fragment. Can somebody please advise how this can be achieved? I have lost couple of hours in figuring out how this can be achieved? Thanks in advance for your help.
XML for third Fragment is below. Is there a way to display EditText, Send Button and Chatlist in the same Fragment? Chatlist is not a problem. The real issue is to set EditText and Send Button.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/newMessageContainer"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/newMessage"
android:focusedByDefault="false"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/send"
android:text="Send"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/messageList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:layout_below ="#id/appbar"
android:layout_above="#id/newMessageContainer"
/>
</RelativeLayout>
EDIT
See Fragment.java file that I have implemented. I am getting error possibly due to ConstraintLayout
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
RecyclerView rv = (RecyclerView) inflater.inflate(
R.layout.fragment_cheese_list, container, false);
setupRecyclerView(rv);
return rv;
}
private void setupRecyclerView(RecyclerView recyclerView) {
recyclerView.setLayoutManager(new
LinearLayoutManager(recyclerView.getContext()));
recyclerView.setAdapter(new
SimpleStringRecyclerViewAdapter(getActivity(),
getRandomSublist(Cheeses.sCheeseStrings, 30)));
}
Here is your code updated. Just design like this your are passing wrong way there is link below where you can learn to code android app and is pretty mainted by developer.
Set fragment like this and pass layout as I have passed
private RecyclerView recyclerView;
private MyAdapter myAdapter;
#Override
public View onCreate(Bundle savedInstanceState){
myAdapter=new MyAdpter();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sample, parentViewGroup, false);
recyclerView= rootView.findViewById(R.id.recyelerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(c);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(myAdapter);
return rootView;
}
private void setupRecyclerView(RecyclerView recyclerView) {
recyclerView.setLayoutManager(new
LinearLayoutManager(recyclerView.getContext()));
recyclerView.setAdapter(new
SimpleStringRecyclerViewAdapter(getActivity(),
getRandomSublist(Cheeses.sCheeseStrings, 30)));
}
Please follow this if you are new
https://guides.codepath.com/android/Using-the-RecyclerView
Try this it work for me also got button click. And keep button click code on Fragment not in recyclerview
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/button"
android:layout_width="88dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="#+id/editText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/editText"
app:layout_constraintTop_toTopOf="#+id/editText" />
<EditText
android:id="#+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/button"
app:layout_constraintStart_toStartOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

How do I show sibling views at the end of viewPager?

The FrameLayout and TextView are not visible even after placing them in ScrollView.
The ViewPager and FrameLayout are replaced with different android.support.v4.app.Fragmentgments.
I want FrameLayout and TextView to be displayed at the end of ViewPager(after scrolling if it exceeds screen height).
<?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">
<include
layout="#layout/layout_appbar" />
<ScrollView
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:layout_width="match_parent"
android:id="#+id/view_container"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_gravity="center_horizontal"
android:text="#string/app_name"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
TLDR; Simply add ScrollView and FrameLayout containers inside a layout, inflate this layout inside a Fragment, add child fragments to those FrameLayout containers in the onViewCreated() of this fragment, return this fragment from the getItem() of PagerAdapter.
Inflate following layout in your MainActivity/MainFragment,
R.layout.frag_main:
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
Setup the ViewPager with some PagerAdapter and return the required fragment from the getItem() method of the adapter like this
#Override
public Fragment getItem(int position) {
return ViewPagerFragment.newInstance(position);
}
inside ViewPagerFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = null;
int position = getArguments().getInt(ARG_POSITION);
switch (position) {
case 0:
view = inflater.inflate(R.layout.page_0, container, false);
break;
case 1:
view = ... //page 1 layout
break;
case 2:
view = ... //page 2 layout
break;
}
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (view.findViewById(R.id.view_container2) != null) {
getChildFragmentManager().beginTransaction()
.add(R.id.view_container, new FrameLayoutFragment())
.commit();
}
}
Now for a page at position in the ViewPagerFragment, you can inflate
R.layout.page_0:
<ScrollView
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<--your ViewPagerFragment content here-->
<FrameLayout
android:layout_width="match_parent"
android:id="#+id/view_container"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
There you have it
Different fragments for ViewPager and FrameLayout
Since FrameLayoutFragment is added to the bottom of your ViewPagerFragment, it is visible after scrolling down.

Specify where ListFragment goes in activity_main.xml

My activity_main.xml is evenly split vertically 3 ways with LinearLayout. I would like to fill the bottom LinearLayout with a ListFragment and populate it with data.
Currently, the ListFragment ignores the 3 LinearLayout and just places itself on top of them.
LstFragment.java
public class LstFragment extends ListFragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragmentlayout, container, false);
// Create an array of string to be data source of the ListFragment
String[] datasource={"English","French","Khmer","Japanese","Russian","Chinese"};
// Create ArrayAdapter object to wrap the data source
ArrayAdapter<String> adapter=new ArrayAdapter<String>(getActivity(),R.layout.rowlayout,R.id.txtitem,datasource);
// Bind adapter to the ListFragment
setListAdapter(adapter);
// Retain the ListFragment instance across Activity re-creation
setRetainInstance(true);
return rootView;
}
// Handle Item click event
public void onListItemClick(ListView l, View view, int position, long id){
ViewGroup viewg=(ViewGroup)view;
TextView tv=(TextView)viewg.findViewById(R.id.txtitem);
Toast.makeText(getActivity(), tv.getText().toString(),Toast.LENGTH_LONG).show();
}
}
MainActivity.java
public class MainActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LstFragment lstfragment=(LstFragment)getSupportFragmentManager().findFragmentByTag("lstfragment");
if(lstfragment==null){
lstfragment=new LstFragment();
FragmentTransaction transact=getSupportFragmentManager().beginTransaction();
transact.add(android.R.id.content,lstfragment,"lstfragment");
transact.commit();
}
}
}
activity_main.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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:id="#+id/topSection">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Testing"
android:id="#+id/textView3" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:id="#+id/middleSection">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Yo"
android:id="#+id/textView2"
android:layout_gravity="center_horizontal" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:id="#+id/bottomSection">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="WhatUP"
android:id="#+id/textView"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
There are two more simple .xml layout files called fragmentlayout.xml which contains a simple ListView #id/android:list and a rowlayout.xml which has a single TextView #id/textitem.
Replace
android:layout_height="fill_parent"
with this line
android:layout_height="0dp"
inside all the three child linear layouts
Reason
android.R.id.content gives you the root element of a view, without having to know its actual name/type/ID. That's why your Fragment is appearing at the top of everything.
You are trying to add your Fragment to wrong container here
transact.add(android.R.id.content,lstfragment,"lstfragment");
Solution
Add this
<FrameLayout
android:layout_width="fill_parent"
android:id="#+id/fragment_container"
android:layout_height="fill_parent">
</FrameLayout>
after 3rd LinearLayout but before closing the root LinerarLayout
then change to
transact.add(R.id.fragment_container,lstfragment,"lstfragment");
Also,
in all of the LinearLayout use this android:layout_height="wrap_content"

Fragment Transaction

I have a ListFragment with a floating action button. When the button is clicked, i want to replace the ListFragment with a CreateListFragment. Instead, the CreateListFragment is placed on top of the ListFragment and the button and textview from the ListFragment are still visible. I am not sure what went wrong. How do I completely replace the ListFragment with the CreateListFragment?
Here is the screenshot before the button is clicked
http://i.stack.imgur.com/k2HxP.png
Here is a screenshot after the button is clicked
http://i.stack.imgur.com/TYN47.png
list_fragment
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listFrame">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fab"
android:layout_gravity="bottom|end"
app:backgroundTint="#color/colorAccent"
android:src="#drawable/create"/>
<TextView
android:id="#+id/tvEmpty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:hint="No Shopping Lists Yet"
android:layout_gravity="center"
android:textSize="20sp"/>
</FrameLayout>``
createlist_fragment
<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:padding="10dp"
tools:context="com.lavineoluoch.helloworld.swiftpay.app.CreateListFragment">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/etListTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/title"/>
<EditText
android:id="#+id/etAddItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/items"/>
<RelativeLayout
android:id="#+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/btnEditItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btnEdit"
android:background="#color/colorPrimary"
android:textColor="#color/white"
/>
</RelativeLayout>
</LinearLayout>
ListFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.list_fragment, container, false);
fab = (FloatingActionButton)view.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CreateListFragment createListFragment = new CreateListFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.listFrame,createListFragment);
fragmentTransaction.commit();
}
});
return view;
}
In your root view for your Fragments insert this line of code:
android:background="?android:windowBackground"
As you have a see through background your view can still see the reminiscence of the replaced Fragment as the view hasn't yet updated.
The above answer should solve your problem, however I would recommend re-structuring your approach and instead launching a new Activity which contains the CreateListFragment when the FAB is pressed. Doing so would result in easier to maintain code which is also easier to read and would be best practice. It would also mean that the user can press their back button and navigate back to ListActivity/ListFragment without you needing to manually handle Fragment back stacks.

FAB position changes when listview's setAdapter method is called

I'm using this library for the fab implementation.
As you can see in this video, the fab position is changing when the fragment loads.
After debugging it, I found that the listview "setAdapter()" method causes the position change.
I don't have a clue why it's happening..
My layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:theme="#style/AppTheme.ActionBar" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/toolbar">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/sad_face"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_leagues" />
</LinearLayout>
</FrameLayout>
<com.melnykov.fab.FloatingActionButton
android:id="#+id/fab_new_league"
android:src="#drawable/ic_action_add"
app:fab_colorNormal="#color/orange"
app:fab_colorPressed="#color/redDark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignBottom="#id/toolbar"
android:layout_marginBottom="-28dp"
android:layout_marginRight="28dp"
android:elevation="8dp"/>
</RelativeLayout>
My fragment
public class LeagueListFragment extends MyFragment {
#InjectView(android.R.id.list) ListView mListView;
#InjectView(android.R.id.empty) LinearLayout mEmpty;
public static Fragment newInstance() {
return new LeagueListFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_league_list, container, false);
ButterKnife.inject(this, view);
// Fetch league list and set up adapter
List<League> list = League.getAll();
mAdapter = new LeagueAdapter(getActivity(), list);
// Set up ListView
mListView.setEmptyView(mEmpty);
mListView.setDivider(new ColorDrawable(getResources().getColor(R.color.gray)));
mListView.setDividerHeight(2);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
return view;
}
}
Margin changes in the runtime on pre-Lollipop because shadow mustn't be taken into account when margins are set.
Try to disable the shadow by :
fab:fab_shadow="false"
Fixing the issue is not expected for now.. (See makovkastar answer)

Categories

Resources