Issue
Every time I call the OnBind() method inside my holders, views within them will flash or blink or maybe even fade.
I'm just pretty lost as to why, I've tried a number of things.
Changing them to have null as a background or have them all be a solid color.
Making sure nothing is gone at any point.
Removed any animations.
Asked Google a thousand times, a thousand ways.
Searched on here.
Thoughts
I've always thought that I would have to eventually try and hide it with animations and styling. Seeing it as just a side effect of the binding.
This is part of a larger project, obviously. So I still have to do all the animations, that's why I haven't done it for this yet. Figured I'd just ask and see if anyone could help find the solution another way in the meantime.
Any help, tips or advice would be great. Hopefully the code links work and are build able for everyone.
Thanks,
Jon.
Code
I'm not sure how much code I need to add in here, so I'll go small at first. If more should be added please let me know and I will. However I put it all on Github and Dropbox(Example Apk & Zip).
Links are at the bottom.
HeaderHolder.java
public class HeaderHolder extends BaseHolder {
#Bind(R.id.header_title_text)
TextView _titleTextView;
#Bind(R.id.header_status_image)
ImageView _statusImageView;
#BindDrawable(R.drawable.ic_selected)
Drawable _statusSelected;
#BindDrawable(R.drawable.ic_non_selected)
Drawable _statusNonselected;
private Header _header;
public HeaderHolder(View root, HolderCallBacks callbacks) {
super(null, root, callbacks);
}
#Override
public void OnBind(Base model) {
this._header = (Header) model;
String n = model._name();
this._titleTextView.setText(n);
this._statusImageView.setImageDrawable(this._header._iconset()._selected()
? this._statusSelected : this._statusNonselected);
}
#OnClick(R.id.header_item_wrapper)
public void _headerClick(View view) {
this._callbacks.OnHolderClick(view, this._header);
}
}
IconsetHolder.java
public class IconsetHolder extends BaseHolder {
#Bind(R.id.iconset_icon_recycler)
RecyclerView _iconsRecycler;
private AdapterCallBacks _adapterCallbacks;
public IconsetHolder(Context context, View root, AdapterCallBacks callbacks) {
super(context, root, null);
this._adapterCallbacks = callbacks;
}
#Override
public void OnBind(Base model) {
Iconset i = (Iconset) model;
this._iconsRecycler.setLayoutManager(new GridLayoutManager(
this._context, i._span(), GridLayoutManager.HORIZONTAL, false));
this._iconsRecycler.setAdapter(new ModelsAdapter(i._icons(), this._adapterCallbacks));
}
}
item_header.xml
<?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:id="#+id/header_item_wrapper"
android:layout_width="wrap_content"
android:layout_height="56dip"
android:background="#595959"
tools:context=".views.adapters.holders.HeaderHolder">
<TextView
android:id="#+id/header_title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:textColor="#fff8f8f8"
android:gravity="center_vertical"
android:text="ICONSET"
android:textSize="24sp"
android:layout_centerVertical="true" />
<ImageView
android:id="#+id/header_status_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="12dp"
android:gravity="center_vertical"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
item_iconset.xml
<?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:id="#+id/iconset_item_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#null"
tools:context=".views.adapters.holders.IconsetHolder">
<android.support.v7.widget.RecyclerView
android:id="#+id/iconset_icon_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:background="#595959"
android:layout_marginBottom="16dp"
/>
</RelativeLayout>
Example Links Removed
RecyclerView has some built in animations to it, using the DefaultItemAnimator. Specifically when you call notifiyItemChanged() it does a fade animation for the changing of the data in the ViewHolder. If you would like to disable this you can use the following:
RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); // your recycler view here
if (animator instanceof DefaultItemAnimator) {
((DefaultItemAnimator) animator).setSupportsChangeAnimations(false);
}
This will disable the item changed animation (the fade you are seeing).
Related
I am testing the behavior of DataBinding observable when it comes to use a LiveData vs. ObservableInt.
I have simple layout with a button that triggers a counter for both LiveData & ObservableInt variables that I store in the ViewModel, I update their values using BindingAdapter
Both LiveData & ObservableInt variables count up normally; but when there is a device configuration change (screen rotation for my test), the ObservableInt countinues count up with button hits, although the LiveData dismisses one or two counts.
Below gif will illustrate more
My question is how to solve this problem?
I mainly need a LiveData for further Transformations
Layout
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="viewmodel"
type="com.example.android.databindingobservableintlivedata.MyViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:id="#+id/observableint_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ObservableInt: " />
<TextView
android:id="#+id/observableint_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
app:textValueForObservableInt="#{viewmodel.countObservableInt}" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center">
<TextView
android:id="#+id/livedata_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LiveData: " />
<TextView
android:id="#+id/livedata_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
app:textValueForLiveData="#{viewmodel.countLiveData}" />
</LinearLayout>
<Button
android:id="#+id/btn_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="16dp"
android:onClick="#{() -> viewmodel.onCount()}"
android:text="Count" />
</LinearLayout>
</layout>
Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
mBinding.setViewmodel(viewModel);
mBinding.setLifecycleOwner(this);
}
}
ViewModel
public class MyViewModel extends ViewModel {
public MutableLiveData<Integer> countLiveData = new MutableLiveData<>(0);
public ObservableInt countObservableInt = new ObservableInt(0);
public void onCount() {
countObservableInt.set(countObservableInt.get() + 1);
int value = countLiveData.getValue() == null ? 0 : countLiveData.getValue();
countLiveData.postValue(value + 1);
}
}
BindingAdapters
public class BindingAdapters {
#BindingAdapter("textValueForObservableInt")
public static void bindObservableIntInText(TextView text, ObservableInt value) {
text.setText(String.valueOf(value.get()));
}
#BindingAdapter("textValueForLiveData")
public static void bindLiveDataIntegerInText(TextView text, MutableLiveData<Integer> value) {
text.setText(String.valueOf(value.getValue()));
}
}
Post value of LiveData:
Basically this method indicates that, any value given to LiveData can be/should be called from background thread (other than main thread) would reflect on main thread with updated value.
Meaning that, if you've got two consecutive calls to LiveData about postValue() then only last value would be dispatched!
In your case, countLiveData.postValue(value + 1) this line gets impacted on post-increment of value if there're too frequent calls to this method, which in case only gets updated for last value but not on consecutive ones.
Set Value of LiveData:
This method requires that call must be made from Main thread, resulting UI gets reflected/updated every time no matter how many calls you've made. None of intermediate calls get discarded.
TL;DR
If you've to update/set value from background thread then use postValue() method otherwise use setValue() when on Main thread.
It takes a while for device rotation when I have continuous hits on the button, and suddenly rotate the device.
Reason is that when you call setValue() on main thread before rotating device, each calls must update the UI consecutively, resulting delay on rotation stuff (Holds the UI updates before configuration change happen). That's why it lags/delay on rotation before all setValue() call completes UI updates (this line in your particular case: app:textValueForLiveData="#{viewmodel.countLiveData}").
I have an XML layout file that has a TextView within a CoordinatorLayout.
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".SpecificProgramSelectionActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="75dp"
android:id="#+id/saved_program"
android:text="Empty"
android:textAlignment="center"
android:gravity="fill"
android:textSize="20dp"
android:background="#drawable/program_selection_border"
android:textColor="#color/black"
android:clickable="true"
android:focusable="true"
android:onClick="addToSavedPrograms"
android:paddingTop="5dp"
android:paddingBottom="5dp"/>
And this code that inflates the layout and adds it into a Linear Layout in the activity's view.
for (PlayerWithObjectives player : players){
name = player.getName();
for (String objective : player.getObjectives()){
objectives.add(objective);
}
nameView = inflater.inflate(R.layout.inflatable_player_name_view, null);
((TextView)nameView.findViewById(R.id.saved_program)).setText(name);
((TextView)nameView.findViewById(R.id.saved_program)).setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
((TextView)nameView.findViewById(R.id.saved_program)).setTextSize(20);
linearLayout.addView(nameView);
}
(This is the activity's layout XML)
<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"
tools:context=".SpecificProgramSelectionActivity"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/specific_program_selection_linear_layout">
</LinearLayout>
</ScrollView>
Everything looks fine in the app when I run it. Every inflated view shows up, the only issue is that the method that I specified in the onClick attribute for the inflated TextView does not get called. Why is that? Here is the method that is supposed to be called
public void addToSavedPrograms(View view){
String name = (String) (((TextView)view.findViewById(R.id.saved_program)).getText());
namesToSend.add(name);
editor.putStringSet("Tracked Players", namesToSend);
editor.commit();
Toast.makeText(getApplicationContext(),name + " was saved to preferences.", Toast.LENGTH_SHORT);
}
Why doesn't the method get called? I already saw all the other threads about using setContent() and stuff but that didn't work and it was not explained that great in the answer. Any help would be greatly appreciated.
public class YourActivity extends AppCompatActivity implements OnClickListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textview=(TextView)findViewById(R.id.saved_program);
textview.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.saved_program:
//call your function here
default:
break;
}
}
you can do it like this.
Update:
First off, thank you to everybody that commented, your help was greatly appreciated. Your no judgment assistance is an awesome and welcome change from a lot of what I have experienced and seen on in this community.
Secondly, I figured out my issue. Or got my code to work at least. Once I got a better understanding of inflating layouts I changed this line of code
nameView = inflater.inflate(R.layout.inflatable_player_name_view, null);
To
nameView = (TextView) inflater.inflate(R.layout.inflatable_add_player_name_view, linearLayout, false);
The difference is that When you inflate, it returns an object that is the same type as the top parent in the specified layout file (Which in this case is "R.layout.inflatable_player_name_view"). So I changed nameView to a TextView object and cast the returned object as a TextView. Then I specified the wanted parent layout (To get the right layoutParams) and put false so that it does not attach it automatically to that parent layout. After that I simply made the alterations to the textView that I wanted, like setting the text values and whatnot, and then manually added it to the parent linearlayout that I wanted. After doing this there was not even a need to set an onClickListener programmatically because the android:onClick method worked just fine.
I'm developing an Android app for an online blog that retrieves data from its API (the company made it so I could use it in it, so it can be modified).
The app shows a ListView with n blog entries on load. The thing is I've spent the last three days searching for a way to add a Previous/Next button at the bottom of said ListView, just to finally give up and try another way.
I've seen apps update and append contents pulled from a server to a list (not sure which type) while the user scrolls up and down on it.
Is this possible? If so, how can it be done?
Any revealing piece of information, example (as simple as it may be) or help would be much appreciated!
EXTRA INFO
I'm loading the ListView in a LinearLineout, which is called in the onCreate method.
content_main.xml
<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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.company.myApp.MainActivity"
tools:showIn="#layout/app_bar_main"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#color/myGrey"
android:scrollbars="none"
android:visibility="visible" />
</LinearLayout>
</LinearLayout>
I also use a custom adapter to fill the ListView with the data retrieved. This data is retrieved by a custom class and stored in a List and that list is then passed as a parameter to the method I use to set such adapter.
public class AdaptadorPosts extends ArrayAdapter {
public AdaptadorPosts(Context context, List objects) {
super(context, 0, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = convertView;
if (null == convertView) {
v = inflater.inflate(R.layout.lista_posts, parent, false);
}
TextView titulo = (TextView)v.findViewById(R.id.titulo);
TextView resumen = (TextView)v.findViewById(R.id.resumen);
TextView fecha = (TextView)v.findViewById(R.id.fecha);
TextView autor = (TextView)v.findViewById(R.id.autor);
Post item = (Post) getItem(position);
titulo.setText(Html.fromHtml(item.getTitulo()));
if(item.getResumen().isEmpty() || item.getResumen().equals(null)) {
resumen.setText("¡No hay resumen!");
} else {
resumen.setText(Html.fromHtml(item.getResumen()));
}
fecha.setText(Html.fromHtml(item.getFecha()));
autor.setText(Html.fromHtml(item.getAutor().getNombre()));
return v;
}
}
If I understand correctly you want to:
Add a Prev/Next button on the bottom of your screen
You have endless content which you want to show dynamically
The first can be easily achieved by using RelativeLayout and for the second you should use RecyclerView.
For your layout you can use something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/light_gray">
<android.support.v7.widget.RecyclerView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:scrollbars="none"
android:visibility="visible"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:src="#drawable/btn_prev"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:src="#drawable/btn_next"/>
</RelativeLayout>
If you want your buttons to be directly below the list, you can attach them by using android:layout_below="#id/lv" and removing android:layout_alignParentBottom="true"
The Android RecyclerView displays a given number of items (e.x. 10) and preloads some of the next and previous items. It's ideal for endless lists. If you want to add items to it dynamically, you need to do that in the adapter by adding the item to the list and calling the notifyItemInserted(int position) method.
I've looked at this question here, however I still cannot find out what I'm doing wrong. There are no errors in Logcat and there definitely is data being passed to it to be made. Here's my setup:
This is all taking place below manually placed elements that I have placed in Android Studio. I have a ScrollView. Inside that ScrollView, I have a LinearLayout, parentLayout, that get's passed to this class. This method is supposed to add another Horizontal LinearLayout, layout, parentLayout. Then it is supposed to add a TextView, titleDisplay, and two Buttons to layout. So far I have only programmed just layout and titleDisplay. I tested it, and nothing was added. So before I program the other two buttons, I would like to know what I am doing wrong. Here's the Java Code:
public class FollowupOption {
private String displayName;
private JSONObject jsonInformation;
private Context context;
private LinearLayout parentLayout;
private LinearLayout layout;
private TextView titleDisplay;
private Button deleteButton, editButton;
public FollowupOption(String displayName, JSONObject jsonInformation,
Context context, LinearLayout parentLayout){
this.displayName = displayName;
this.jsonInformation = jsonInformation;
this.context = context;
this.parentLayout = parentLayout;
buildLayout();
}
private void buildLayout(){
//Horizontal Linear Layout to hold everything
this.layout = new LinearLayout(context);
this.layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
this.layout.setOrientation(LinearLayout.HORIZONTAL);
this.parentLayout.addView(this.layout);
//Text View Displaying title of followup option.
this.titleDisplay = new TextView(context);
try {
this.titleDisplay.setText(this.jsonInformation.getJSONObject("list").getString("title"));
} catch(JSONException e){ e.printStackTrace(); }
this.titleDisplay.setTextColor(0x8f142a); //Black
this.titleDisplay.setTextSize(18);
this.titleDisplay.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
this.layout.addView(this.titleDisplay);
}
}
Here's my XML:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="38dp"
android:orientation="horizontal">
<TextView
android:id="#+id/textView15"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.22"
android:gravity="center"
android:text="#string/followup_text"
android:textColor="#color/myRed"
android:textSize="18sp" />
<Button
android:id="#+id/followup_add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:text="#string/plus"
android:textAlignment="center"
android:textColor="#android:color/holo_green_dark"
android:textSize="30sp"
android:textStyle="bold" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="279dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="7dp">
<LinearLayout
android:id="#+id/followup_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
<Button
android:id="#+id/followup_new_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/new_followup_text" />
</LinearLayout>
</merge>
If someone could let me know what I am doing wrong or a good way to debug something like this, that would be appreciated.
Are you adding this.layout view to some view?
UPD: The problem is with your text color. Consider using the Color class to get color from its hex value or constants from that class.
Does your XML view (without the addition of the dynamic layout) take up the entire screen?
The new LinearLayout view will be added below the button. If the button is at the bottom of the screen, the layout will be added off the screen and therefore not visible.
You should add your new layout to the scroll view instead.
EDIT 2:
In my MainActivity I have a function (displayData) that displays the substitutions for my school.
public void displayData(List<Schoolday> results) {
TabLayout mainTabLayout = (TabLayout) findViewById(R.id.mainTabLayout);
ViewPager mainViewPager = (ViewPager) findViewById(R.id.mainViewPager);
// draw the tabs depending on the days from the file
mainTabLayout.removeAllTabs();
for (int n = 0; n < results.size(); n++) {
List<Subject> subjectsToDisplay = new ArrayList<>();
if (myPreferences.getBoolean(SHOW_WHOLE_PLAN, true)) {
subjectsToDisplay = results.get(n).getSubjects();
} else {
List<Subject> tempSubjectsToDisplay;
tempSubjectsToDisplay = results.get(n).getSubjects();
for (int i = 0; i < tempSubjectsToDisplay.size(); i++) {
if (tempSubjectsToDisplay.get(i).getCourse().contains(myPreferences.getString(CLASS_TO_SHOW, "None"))) {
subjectsToDisplay.add(tempSubjectsToDisplay.get(i));
}
}
}
results.get(n).setSubjects(subjectsToDisplay);
// only create a tab if there's any information to show within that tab
if (results.get(n).getSubjects().size() > 0) {
mainTabLayout.addTab(mainTabLayout.newTab().setText(results.get(n).getDate().substring(0, 6)));
}
}
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), mainTabLayout.getTabCount(), results);
mainViewPager.setAdapter(pagerAdapter);
mainViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mainTabLayout));
mainTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
mainViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
This is my main 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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.TabLayout
android:id="#+id/mainTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabGravity="fill" />
<android.support.v4.view.ViewPager
android:id="#+id/mainViewPager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/mainTabLayout" />
</RelativeLayout>
And this is the layout of the fragment that represents a page in the ViewPager:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/mainSwipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/mainRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
Whenever a refresh is triggered by the SwipeRefreshLayout I need the function displayData to be called.
How can I call this function since the call comes from within a fragment/page from the ViewPager and displayData is not static?
Old question:
I've been searching around quite a while but couldn't find an answer. Maybe I've searched for the wrong thing - just pointing me to that would already help.
My project (Vertretungsplan on github) displays the substitution plan for my school which is available to view/download as an xml file (xml file from school website). I then display the data in my app.
I have a TabLayout (different tabs represent different days) and a connected ViewPager. Each page is using a fragment. Each fragment includes a RecyclerView (to display the results) which is wrapped in a SwipeRefreshLayout.
When I want to refresh the data with the SwipeRefreshLayout I need to download all the data again and then update all the pages as well as the TabLayout(a new day might have a been added so a new tab will be needed). Since my refresh happens inside a fragment but I'm referencing the TabLayout as well as the ViewPager from my MainActivity I have no clue how to properly access all the elements in order to update the content.
My idea was to set up a Broadcast to let my MainActivity know that it needs to refresh the page since it originally set up the whole layout but maybe there is a better solution for that?
I'm kinda new to stackoverflow so feel free to correct me in the way of asking things here! If there's anything other information you need just ask me!
I appreciate your help!!
There are a couple ways to implement what you are asking. The most direct way is to create an interface for the Activity that the Fragment uses. See the docs here:
http://developer.android.com/training/basics/fragments/communicating.html
The other option, which decouples the Fragment from the Activity (which some may see as an advantage) is to use an Intent. With that approach, you need to look into the onNewIntent method, as it is not obvious exactly how it works.
Either one should be fine, especially since you are exploring ideas at this point.