I have an android app that has two fragments that pass data from fragmentA to fragmentB. I can load all the data correctly but when I change the screen orientation it all reloads. I have set up the onSaveInstanceState and onViewStateRestored methods in the fragment I want to keep the state in, but nothing stays when the screen orientation changes.
The main problem that needs to be fixed is when text is loaded into the TextView in FragmentB - it needs to stay there when the screen orientation is changed.
MainActivity.Java
package com.example.tourguide;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements FragmentA.FragmentAListener, FragmentB.FragmentBListener {
private FragmentA fragmentA;
private FragmentB fragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA = new FragmentA();
fragmentB = new FragmentB();
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA());
ft.replace(R.id.container_b, new FragmentB());
ft.commitNow();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onInputASent(CharSequence input) {
fragmentB.updateEditText(input);
}
#Override
public void onInputBSent(CharSequence input) {
fragmentA.updateEditText(input);
}
}
FragmentA.Java
package com.example.tourguide;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.ListFragment;
public class FragmentA extends ListFragment implements AdapterView.OnItemClickListener {
private FragmentAListener listener;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String[] locationList = getActivity().getResources().getStringArray(R.array.location_list);
updateEditText(locationList[position]);
listener.onInputASent(locationList[position]);
}
public interface FragmentAListener {
void onInputASent(CharSequence input);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_a, container, false);
return v;
}
#Override
public void onListItemClick(#NonNull ListView l, #NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id);
}
public void updateEditText(CharSequence newText) {
//editText.setText(newText);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentAListener) {
listener = (FragmentAListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentAListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter arrayAdapter = ArrayAdapter.createFromResource(getActivity(), R.array.location_list, android.R.layout.simple_list_item_1);
setListAdapter(arrayAdapter);
getListView().setOnItemClickListener(this);
}
}
FragmentB.Java - This is the fragment that needs to be keep the string inside the TextView when the screen is rotated
package com.example.tourguide;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class FragmentB extends Fragment {
private FragmentBListener listener;
private TextView resultsFrag;
private static final String KEY_TITLE = "title_key";
private String stateObject;
public interface FragmentBListener {
void onInputBSent(CharSequence input);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_b, container, false);
resultsFrag = v.findViewById(R.id.tvFragmentB);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 1", Toast.LENGTH_SHORT).show();
}
return v;
}
public void updateEditText(CharSequence newText) {
String newOption = newText.toString();
stateObject = newText.toString();
Resources res = getResources();
String[] locationDesc = res.getStringArray(R.array.location_description);
if (newOption.equals("Calgary")) {
resultsFrag.setText(locationDesc[0]);
} else if (newOption.equals("Victoria")) {
resultsFrag.setText(locationDesc[1]);
} else if (newOption.equals("Vancouver")) {
resultsFrag.setText(locationDesc[2]);
} else if (newOption.equals("Toronto")) {
resultsFrag.setText(locationDesc[3]);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentBListener) {
listener = (FragmentBListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentBListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_TITLE, resultsFrag.getText().toString());
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 2", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 3", Toast.LENGTH_SHORT).show();
}
}
}
fragment_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_light"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="#+id/tvFragmentB"
android:layout_width="match_parent"
android:layout_height="602dp" />
</LinearLayout>
Strings
<resources>
<string name="app_name">Tour Guide</string>
<string-array name="location_list">
<item>Calgary</item>
<item>Victoria</item>
<item>Vancouver</item>
<item>Toronto</item>
</string-array>
<!-- Descriptions for the locations -->
<string-array name="location_description">
<item>This is a big description for CALGARY - THIS needs to load in for more information regarding CALGARY</item>
<item>This is a big description for VICTORIA - THIS needs to load in for more information regarding VICTORIA</item>
<item>This is a big description for VANCOUVER - THIS needs to load in for more information regarding VANCOUVER</item>
<item>This is a big description for TORONTO - THIS needs to load in for more information regarding TORONTO</item>
</string-array>
</resources>
fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_green_light"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="206dp" />
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/container_a"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/container_b"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
They are saved, but you are replacing them. Use this
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA());
ft.replace(R.id.container_b, new FragmentB());
ft.commit();
}
Please note that fragment instantiation is pretty much the ONLY scenario in which this check yields correct and expected results.
Do not keep a reference to a Fragment, unless it is obtained via findFragmentByTag + instantiation. You might want to use commitNow to get reliable results in this case.
EDIT: Update with more complete code:
public class MainActivity extends AppCompatActivity implements FragmentA.FragmentAListener, FragmentB.FragmentBListener {
private FragmentA fragmentA;
private FragmentB fragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA(), "fragmentA");
ft.replace(R.id.container_b, new FragmentB(), "fragmentB");
ft.commitNow();
}
fragmentA = getSupportFragmentManager().findFragmentByTag("fragmentA");
fragmentB = getSupportFragmentManager().findFragmentByTag("fragmentB");
}
I am developing an app on android studio (Java)
I have created a tabLayout that swipes between two fragments using a viewPager2 + Fragment State Adapter
On fragment02, I have animated a textView.
When I swipe onto the fragment the animation plays on loop, as it should.
However, if I swipe off the fragment and then back on, the animation is no longer playing.
I really need the animation to continue.
Any advice is welcome and I thank you in advance :)
Please be aware I am rather new to this.
// MainActivity.java
package Zoomie.App;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("Welcome");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ViewPager2 viewPager2 = findViewById(R.id.ViewPager);
viewPager2.setAdapter(new FragmentPagerAdapter(this));
TabLayout tabLayout = findViewById(R.id.tabLayout);
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
switch (position) {
case 0: {
tab.setText("Fragment 01");
break;
}
default: {
tab.setText("Fragment 02");
break;
}
}
}
});
tabLayoutMediator.attach();
}
}
// FragmentPagerAdapter.java
package Zoomie.App;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
public class FragmentPagerAdapter extends FragmentStateAdapter {
public FragmentPagerAdapter(#NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
#NonNull
#Override
public Fragment createFragment(int position) {
switch (position){
case 0:
return new Fragment01();
default:
return new Fragment02();
}
}
#Override
public int getItemCount() {
return 2;
}
}
// Fragment02.java
package Zoomie.App;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
public class Fragment02 extends Fragment {
public Fragment02() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView=inflater.inflate(R.layout.fragment_02, container, false);
TextView fade01 = (TextView) rootView.findViewById(R.id.textView_fade_01);
Animation fade = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_animation);
fade01.startAnimation(fade);
return rootView;
}
}
// fade_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0"
android:toAlpha=".5"
android:duration="375"
android:repeatMode="reverse"
android:repeatCount="infinite"
/>
</set>
You should move the loading animation method into onResume() lifecycle method. In your case:
private TextView fade01;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState
) {
View rootView = inflater.inflate(R.layout.fragment_02, container, false);
fade01 = (TextView) rootView.findViewById(R.id.textView_fade_01);
return rootView;
}
#Override
public void onResume() {
super.onResume();
Animation fade = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_animation);
fade01.startAnimation(fade);
}
For my academic project, I want create an application with 4 tabs. The first one will show recent games added to a list, the second one will be a search form, the third will show the search result, and the last one will show the details. I currently have created the code for TabView and the 4 tabs. The problem is that I want to perform a search to get the items I have in a list which meet the search criteria on fragment 2, but I don't know how to pass the data from fragment 2 (textView data and spinner) to fragment 3. My code is the following:
MainActivity.java:
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.view.MenuInflater;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setImageResource(R.drawable.ic_search_white_24dp);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
//TabLayout function call
configureTabLayout();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.menu_exit:
finish();
return true;
case R.id.menu_settings:
Toast.makeText(this, "Under Construction", Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
//Tab Layout function declaration
private void configureTabLayout() {
//Getting the tab layout
TabLayout tabLayout = findViewById(R.id.tab_layout);
//Adding Tabs
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_home_white_24dp));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_search_white_24dp));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_results_white_24dp));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_details_white_24dp));
//The TabPagerAdapter instance is then
//assigned as the adapter for the ViewPager and the TabLayout component added
//to the page change listener
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new TabPagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
//Finally, the onTabSelectedListener is configured on the TabLayout instance and
//the onTabSelected() method implemented to set the current page on the
//ViewPager based on the currently selected tab number.
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
TabPagerAdapter.java
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabPagerAdapter extends FragmentPagerAdapter{
int tabCount;
public TabPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.tabCount = numberOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new HomeScreenFragment();
case 1:
return new SearchFormFragment();
case 2:
return new SearchResultsFragment();
case 3:
return new DetailsScreenFragment();
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
SearchFormFragment.java
package gr.pliroforiki_edu.videogamedb;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
/**
* A simple {#link Fragment} subclass.
*/
public class SearchFormFragment extends Fragment {
private Button searchButton;
private EditText gameTitleEditText;
Spinner spinnerGenre;
public SearchFormFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View searchFormView = inflater.inflate(R.layout.fragment_search_form, container, false);
searchButton = searchFormView.findViewById(R.id.searchButton);
gameTitleEditText = searchFormView.findViewById(R.id.game_title_editText);
spinnerGenre = searchFormView.findViewById(R.id.genre_spinner);
ArrayAdapter<CharSequence> genreAdapter = ArrayAdapter.createFromResource(
getActivity(),
R.array.game_genres,
android.R.layout.simple_spinner_item
);
genreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerGenre.setAdapter(genreAdapter);
searchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String filterGameTitle = gameTitleEditText.getText().toString();
int filterGenreId = spinnerGenre.getSelectedItemPosition();
String message = String.format("Game Title: %s\n Genre: %s", filterGameTitle, filterGenreId);
Toast.makeText(getActivity(),message, Toast.LENGTH_LONG).show();
}
});
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_search_form, container, false);
return searchFormView;
}
}
SearchResultsFragment.java
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
/**
* A simple {#link Fragment} subclass.
*/
public class SearchResultsFragment extends Fragment {
TextView infoTextView;
ListView listViewGames;
public SearchResultsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View searchResultsView = inflater.inflate(R.layout.fragment_search_results, container, false);
return searchResultsView;
}
private void findViews()
{
infoTextView = getActivity().findViewById(R.id.info_textView);
listViewGames = getActivity().findViewById(R.id.games_listView);
}
}
I want to archive the following via the fragments:
ListActivity.java
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class ListActivity extends AppCompatActivity {
private TextView textViewInfo;
private ListView listViewBooks;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
// Animation when this Activity appears
overridePendingTransition(R.anim.pull_in_from_right, R.anim.hold);
// Get user filters from Intent
Intent intent = getIntent();
String filterAuthor = intent.getStringExtra("AUTHOR");
String filterTitle = intent.getStringExtra("TITLE");
int filterGenreId = intent.getIntExtra("GENREID", 0);
findViews();
// Show user filters for information
String message = String.format("Author: %s\nTitle: %s\nGenreId: %d",
filterAuthor, filterTitle, filterGenreId);
textViewInfo.setText(message);
DataStore.LoadBooks(filterAuthor, filterTitle, filterGenreId);
//Complex Object Binding
ListAdapter booksAdapter = new SimpleAdapter(
this,
DataStore.Books,
R.layout.list_item,
new String[]{DataStore.KEY_TITLE, DataStore.KEY_AUTHOR, DataStore.KEY_GENRENAME},
new int[]{R.id.book_item_title, R.id.book_item_author, R.id.book_item_genre}
);
listViewBooks.setAdapter(booksAdapter);
listViewBooks.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent detailsIntent = new Intent(ListActivity.this, DetailsActivity.class);
detailsIntent.putExtra(DataStore.KEY_POSITION, position);
startActivity(detailsIntent);
}
});
}
#Override
protected void onPause(){
overridePendingTransition(R.anim.hold, R.anim.push_out_to_right);
super.onPause();
}
private void findViews(){
textViewInfo = findViewById(R.id.textViewInfo);
listViewBooks = findViewById(R.id.listViewBooks);
}
}
Mainactivity.java
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText textAuthor;
private EditText textTitle;
private EditText textGenre;
private Button buttonSearch;
private Spinner spinnerGenre;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DataStore.Init(getApplicationContext());
textAuthor = findViewById(R.id.editTextAuthor);
textTitle= findViewById(R.id.editTextAuthor);
buttonSearch = findViewById(R.id.buttonSearch);
spinnerGenre = (Spinner) findViewById(R.id.spinnerGenre);
ArrayAdapter<CharSequence> genreAdapter = ArrayAdapter.createFromResource(
this,
R.array.book_genres,
android.R.layout.simple_spinner_item
);
genreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerGenre.setAdapter(genreAdapter);
buttonSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String filterAuthor = textAuthor.getText().toString();
String filterTitle = textTitle.getText().toString();
int filterGenreId = spinnerGenre.getSelectedItemPosition();
Intent intent = new Intent(MainActivity.this, ListActivity.class);
intent.putExtra("AUTHOR", filterAuthor);
intent.putExtra("TITLE", filterTitle);
intent.putExtra("GENREID", filterGenreId);
startActivity(intent);
}
});
}
}
Try this
pass value between two fragment using bundle
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabPagerAdapter extends FragmentPagerAdapter{
int tabCount;
public TabPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.tabCount = numberOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new HomeScreenFragment();
case 1:
return new SearchFormFragment();
case 2:
Fragment fragment = new SearchResultsFragment()
Bundle args = new Bundle();
args.putString("Key", "Value");
fragment.setArguments(args);
return fragment;
case 3:
return new DetailsScreenFragment();
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
in your onCreateView(....) of SearchResultsFragment
String value = getArguments().getString("Key");
public class SearchResultsFragment extends Fragment {
TextView infoTextView;
ListView listViewGames;
public SearchResultsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View searchResultsView =
inflater.inflate(R.layout.fragment_search_results, container, false);
String value = getArguments().getString("Key");
return searchResultsView;
}
private void findViews(){
infoTextView = getActivity().findViewById(R.id.info_textView);
listViewGames = getActivity().findViewById(R.id.games_listView);
}
}
hop its help you
There are many ways you can pass objects/values between fragments. In your case, the simplest solution would be to delegate those values to the holding Activity i.e MainActivity.
MainActivity:
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.view.MenuInflater;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
//these will hold your values
String filterGameTitle;
int filterGenreId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setImageResource(R.drawable.ic_search_white_24dp);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
//TabLayout function call
configureTabLayout();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.menu_exit:
finish();
return true;
case R.id.menu_settings:
Toast.makeText(this, "Under Construction", Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
//Tab Layout function declaration
private void configureTabLayout() {
//Getting the tab layout
TabLayout tabLayout = findViewById(R.id.tab_layout);
//Adding Tabs
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_home_white_24dp));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_search_white_24dp));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_results_white_24dp));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_details_white_24dp));
//The TabPagerAdapter instance is then
//assigned as the adapter for the ViewPager and the TabLayout component added
//to the page change listener
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new TabPagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
//Finally, the onTabSelectedListener is configured on the TabLayout instance and
//the onTabSelected() method implemented to set the current page on the
//ViewPager based on the currently selected tab number.
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
SearchFormFragment:
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
/**
* A simple {#link Fragment} subclass.
*/
public class SearchFormFragment extends Fragment {
private Button searchButton;
private EditText gameTitleEditText;
Spinner spinnerGenre;
public SearchFormFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View searchFormView = inflater.inflate(R.layout.fragment_search_form, container, false);
searchButton = searchFormView.findViewById(R.id.searchButton);
gameTitleEditText = searchFormView.findViewById(R.id.game_title_editText);
spinnerGenre = searchFormView.findViewById(R.id.genre_spinner);
ArrayAdapter<CharSequence> genreAdapter = ArrayAdapter.createFromResource(
getActivity(),
R.array.game_genres,
android.R.layout.simple_spinner_item
);
genreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerGenre.setAdapter(genreAdapter);
searchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String filterGameTitle = gameTitleEditText.getText().toString();
int filterGenreId = spinnerGenre.getSelectedItemPosition();
((MainActivity)getActivity()).filterGameTitle = filterGameTitle;
((MainActivity)getActivity()).filterGenreId = filterGenreId;
String message = String.format("Game Title: %s\n Genre: %s", filterGameTitle, filterGenreId);
Toast.makeText(getActivity(),message, Toast.LENGTH_LONG).show();
}
});
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_search_form, container, false);
return searchFormView;
}
}
SearchResultFragment:
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
/**
* A simple {#link Fragment} subclass.
*/
public class SearchResultsFragment extends Fragment {
TextView infoTextView;
ListView listViewGames;
String filterGameTitle;
int filterGenreId;
public SearchResultsFragment() {
// Required empty public constructor
}
#Override
public void onAttach(Context context)
{
filterGameTitle = ((MainActivity)getActivity()).filterGameTitle;
filterGenreId = ((MainActivity)getActivity()).filterGenreId;
super.onAttach(context);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View searchResultsView = inflater.inflate(R.layout.fragment_search_results, container, false);
return searchResultsView;
}
private void findViews()
{
infoTextView = getActivity().findViewById(R.id.info_textView);
listViewGames = getActivity().findViewById(R.id.games_listView);
}
}
You can use interface to send your search string to your activity from fragment 2, and from their you can call all methods in your fragment 3 as fragment3 object will be available to you in your activity, you can make performSearch() in your fragment3 and call it from your activity.
Alternatively you can use something like event bus to avoid the boiler plate code needed to setup interface.
Have a look at this event bus repo https://github.com/greenrobot/EventBus
Register event bus where you want the search string, in your case register the event bus in Fragment3 like this
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
In your Fragment 3 create a function like this
#Subscribe
public void onSearchEvent(String searchString){
//you will get your search string here
}
Now comeback to fragment2 from where you want to send the searchString, you have to put below code from where you want to send searchString, and this posted searchString will be received by fragment 3 in its onSearchEvent method
EventBus.getDefault().post(searchString);
Environment:
Android API 25
Android Studio 2.3.3
I'm trying to add share item to menu and this is my code, I've tried these solution and searching for three days but it doesn't solve my problem
Unable to cast Action Provider to Share Action Provider
why MenuItemCompat.getActionProvider returns null?
Menu xml resource detail_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_share"
android:title="#string/action_share"
app:showAsAction="always"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
</menu>
The Fragment code:
package com.example.poula.sunshine;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.ShareActionProvider;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
/**
* A placeholder fragment containing a simple view.
*/
public class DetailActivityFragment extends Fragment {
private static final String LOG_TAG = DetailActivityFragment.class.getSimpleName();
private static final String FORECAST_SHARE_STRING = "#SunshineApp";
private ShareActionProvider mShareActionProvider;
private String forecastStr;
public DetailActivityFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_detail,menu);
inflater.inflate(R.menu.detail_fragment,menu);
MenuItem menuItem = menu.findItem(R.id.action_share);
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
if(mShareActionProvider != null){
mShareActionProvider.setShareIntent(createShareForecastIntent());
}else{
Log.d(LOG_TAG, "Share Action Provider is null!!");
Toast.makeText(getActivity(), "Share Action Provider is null!!", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Intent intent = getActivity().getIntent();
View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
if( !(intent == null) && intent.hasExtra(Intent.EXTRA_TEXT) ){
forecastStr = intent.getStringExtra(Intent.EXTRA_TEXT);
TextView tv = (TextView) rootView.findViewById(R.id.detail_text);
tv.setText(forecastStr);
}
return rootView;
}
private Intent createShareForecastIntent(){
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, forecastStr+" "+FORECAST_SHARE_STRING);
return shareIntent;
}
}
Issues:
Share item on the bar is not clickable
any ideas on how to solve these two issues ?
i have a little problem with eclipse/android.
i am trying to mak my own paint-app in android. my problem is i can only paint with one color(black) , now i want to add 3 more colors(red,green,blue).
im still a newbie to android developing, and i dont know how i can add that option.
anyone has any suggestions?
here is my code so far
-SingleTouchEventView
package nl.hr.teken0;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
public class SingleTouchActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SingleTouchEventView(this, null));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container,
false);
return rootView;
}
}
}
SingleTouchActivity
package nl.hr.teken0;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
public class SingleTouchActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SingleTouchEventView(this, null));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container,
false);
return rootView;
}
}
}
You can use a color picker. An example: https://code.google.com/p/android-color-picker/
Just import it like other libraries so that the source is in the "src" folder and then add the layout to the preferences file.
Preferences xml file:
<yuku.ambilwarna.widget.AmbilWarnaPreference
android:key="your_preference_key"
android:defaultValue="0xff6699cc"
android:title="Pick a color" />