I created a swipe refresh layout in my android app.
There is a ListView in the main activity fragment and when the user swipes the list view, the app fetches data from the internet to display in the listview.
My problem is that even after fetching the data (correctly), the swipe refresh wheel is not going away from the app.
Here is the code for my main fragment xml file:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main_swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="#+id/listview_forecast"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#00000000"
android:dividerHeight="4dp"/>
</android.support.v4.widget.SwipeRefreshLayout>
And here is the code for my Main activity fragment file (partial)
swipeContainer = (SwipeRefreshLayout) rootView.findViewById(R.id.activity_main_swipe_refresh_layout);
swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.v(TAG, "Swiped!") ;
}
});
I created the refresh listener inside the onCreateView method of the Main activity fragment.
What can I do to correct it?
Once your task is finished call:
swipeContainer.setRefreshing(false);
Related
In my application I have empty activity and plus button which opens new activity in which I type some title and few text fields and then save. When i save that item is added to the 1. activity but not shown. I need to go to some other activity and when i come back its then loaded. Same goes for 2nd item after its added but after there are 2 or more items it always loads all the items, im not using aSyncTask, i just load data from database. Anyone knows what could be the problem?
Is there any itemView.function() that reloads all the items in a activity?
You could use LiveData for that and observe it to your Main Activity.
I assume that you are using ROOM library for your database and MVVM architecture. Here's the example from my project.
public LiveData<List<Todo>> getAllTodo() {
return allTodo;
} //This is from my ViewModel class.
and I observe it from my main activity
viewModel = new ViewModelProvider(this).get(ViewModel.class);
viewModel.getAllTodo().observe(this, new Observer<List<Todo>>() {
#Override
public void onChanged(List<Todo> todos) {
todoAdapter.setTodos(todos);
}
});
Problem was that my xml file that containted RecyclerView was set to wrap contnent so i changed
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/card_gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:padding="2dp"
tools:listitem="#layout/card_item">
</androidx.recyclerview.widget.RecyclerView>
to
android:layout_width="match_parent"
android:layout_height="match_parent"
I am trying to get a list view id from another xml file (fragment_friends.xml) while i am in activity_main.xml layout. I tried 2 ways, but they are not working properly.
Below code will cause the app to crash straight away because i am trying to get an id that does not exist in this layout (activity_main)
Original code
ListView friendList = (ListView) findViewById(R.id.friend_listView);
friendList.setAdapter(friendAdaptor);
Below code works, but i wont be able to insert or display any data into my database.
Try 1 code:
View inflatedView = getLayoutInflater().inflate(R.layout.fragment_friend, null);
ListView friendList = (ListView) inflatedView.findViewById(R.id.friend_listView);
friendList.setAdapter(friendAdaptor);
Below code the database and listView works, but my navbar drawer is gone and i when i try to get back to activity_main, app crashes
Try 2 code
setContentView(R.layout.fragment_friend);
ListView friendList = (ListView) inflatedView.findViewById(R.id.friend_listView);
friendList.setAdapter(friendAdaptor);
app_bar_main.xml
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<!--<include layout="#layout/content_main" />-->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
I believe the root of your problem comes down to a lack of familiarity with the general Android Fragment APIs. That's fine; everyone is new when they start. But it means that your question is quite difficult to answer concisely (beyond "read about Fragments").
You should, of course, start by reading about Fragments: https://developer.android.com/guide/components/fragments.html
Still, I think we can cover things here in brief.
All Fragments must be hosted in an Activity. The normal way to do this is either by adding a <fragment> tag to your activity's xml layout, or by including a <FrameLayout> in your activity's xml layout and then using a FragmentTransaction to dynamically add/replace/remove fragments from that frame.
In your posted code, inside app_bar_main.xml, I see this:
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"/>
This is clearly the place where your fragments will eventually live, but you'll have to add them to the frame yourself in your Java code. You actually have a method that does this already:
private void displaySelectedScreen(int id){
Fragment fragment = ...
if(fragment != null){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.flContent, fragment);
ft.commit();
}
...
}
It looks like this is meant to be used when your user clicks on an item in your navigation drawer, but the concept is the same. If you want your app to always start up with the "friends" fragment displayed, you can add this code to your activity's onCreate() method:
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.flContent, new friend())
.commit();
}
Now you will have a friend fragment to work with!
However, fragment transactions aren't guaranteed to be executed right away, so even though (as a user) you'll always see this friend fragment when the app starts up, you won't necessarily be able to interact with it (as a programmer) immediately after writing this code. So you'll also have to move your call to populateFriendList() from your onCreate() method.
Instead, you should populate the friends list from within the friend fragment itself! Probably the right place to do this is inside the onActivityCreated() method of your fragment.
To find a view from inside a Fragment subclass, you can't just write findViewById() the way you can in an Activity. However, you can write this instead: getView().findViewById()... as long as you're doing this after your onCreateView() method has returned.
Anyway, this answer is getting extremely long even as I try to keep it as short as possible. I hope this is enough information for you to get your app up and running. Good luck.
I am using webview to create a basic web browser,
Currently I have one activity and multiple fragments :
-- Browser
-- something else
-- Something else
in Browser Fragment I have the webview :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".fragments.BrowserFragment">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/webview_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true">
<include
android:id="#+id/button_layout"
layout="#layout/bottom_btn_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
<LinearLayout
android:id="#+id/web_page_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/button_layout"
android:orientation="vertical">
</LinearLayout>
<WebView
android:id="#+id/web_page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/button_layout"/>
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
I am able to save the state of the webview on screen rotation , by using
#Override
public void onSaveInstanceState(Bundle outState) {
if(mWebView != null){
mWebView.saveState(outState);
}
super.onSaveInstanceState(outState);
}
and calling this OnActivityCreated :
mWebView = (WebView)getActivity().findViewById(R.id.web_page);
if (savedInstanceState != null){
mWebView.restoreState(savedInstanceState);
}else{
mWebView.loadUrl(makeUrl(url));
}
This works fine when screen rotates and activity is recreated.
But when I use navigation drawer and replace fragment in the same container and then try to come back to same fragment . The state of webview is lost.
I get the point that onSaveInstanceState() is not called when there is Fragment transaction. So I tried saving the webView state by calling onSaveInstanceState() from OnPause of the fragment. But in that case I get savedInstanceState as null in OnCreateView so I am not able to restore state.
I need to maintain state of multiple webviews and comeBack to them on click of a list.
I also tried saving webview, when onSave() is called in fragment, in a static HashMap in activity and try to assign it to webview of newFragment. But I get Blank screen in that case.
Could someone give me pointers how I can approach this.
I would like to override the back button in an activity so that I can start a fragment, normally within activities I use an intent but as I understand I cannot use an intent to call fragments.
The reason I want to use the back button to start the intent is so it can reload new information from the database, otherwise, if I don't override the back button it will just load the previous fragment with old (cached) data.
My code below which does not work:
#Override
public void onBackPressed(){
handler.removeCallbacksAndMessages(null);
new leftRoom().execute();
Intent intent = new Intent(ActivityChatRoom.this,Fragment_01_Rooms.class);
startActivity(intent);
}
Update:
fragment_01_rooms.xml:
<?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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- android:background="#color/gray_header"-->
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fadeScrollbars="false" >
</ListView>
</LinearLayout>
Update (activity_main.xml):
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/viewpager"
tools:context=".FragmentMain"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Try this:
#Override
public void onBackPressed(){
handler.removeCallbacksAndMessages(null);
new leftRoom().execute();
getSupportFragmentManager().beginTransaction().replace(R.id.viewpager, new Fragment_01_Rooms()).commit();
}
You would have to add a FrameLayout as the container in the activity if you don't already have a container view in which to inflate the fragment. Let me know if you need more clarifications.
EDIT
Thanks a lot for the full activity code. Since you are using a ViewPager, replacing a fragment this way won't work. Now, you mentioned two lines in the onBackPressed you wanted to implement:
handler.removeCallbacksAndMessages(null);
new leftRoom().execute();
What is the role of these two methods and where are they implemented? If these methods update your db, and if Fragment_01_Rooms is the leftmost element in your viewPager, I would suggest you to do this:
In the onResume of your Fragment_01_Rooms, refresh the data that you are going to show the user (if the two lines above already refresh the data, you don't need to do anything).
In the Activity, override onBackPressed and call viewPager.setCurrentItem(0) instead of getSupportFragmentManager...commit().
Let me know if this solves the problem.
#Override
public void onBackPressed(){
handler.removeCallbacksAndMessages(null);
new leftRoom().execute();
}
In your leftRoom AsyncTask onPostExecute call this.
getSupportFragmentManager().beginTransaction().replace(R.id.container, new Fragment_01_Rooms()).commit();
I used Android-PullToRefresh from chrisbanes to show refresh progress in my app.
I load data in AsyncTask, so I start refreshing by calling mPullRefreshListView.setRefreshing();
in onPreExecute method
and stop refreshing by
calling mPullRefreshListView.onRefreshComplete();
in onPostExecute method.
That works fine. But the problem happens when network down. Because I won`t use AsyncTask when network down any more, instead I load local cache.
I don`t want to show the PullToRefresh animations when refreshing if network down, but since it registered the setOnRefreshListener, every time when user pull down the ListView, it shows the refreshing animations, and never got disappear.
I tried to disable the animation by calling mPullRefreshListView.onRefreshComplete();, but it does`t help.
if (!Utils.isNetworkOn()) {
if (mPullRefreshListView.isRefreshing())
mPullRefreshListView.onRefreshComplete();
}
I feel very confused about this, anyone knows how to handle this?
Thanks in advance.
It is better to use SwipeRefreshLayout since Chris Bane's project is no longer maintained:
<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.v4.widget.SwipeRefreshLayout
android:id="#+id/srl_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
In fragment:
private void pullToRefreshForConfiguredList(View view) {
mConfiguredSwipeRefreshLayout = (SwipeRefreshLayout) view
.findViewById(R.id.srl_layout);
mConfiguredSwipeRefreshLayout
.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// call Method to be refreshed
if (mConfiguredSwipeRefreshLayout.isRefreshing())
mConfiguredSwipeRefreshLayout.setRefreshing(false);
}
});
mConfiguredSwipeRefreshLayout.setColorScheme(android.R.color.black,
R.color.red, android.R.color.black, R.color.red);
}