How to save fragment state - android

I have SettingActivity. It contains SettingFragment (with ListPreference) and another AudioSamplingSeekBarFragment(with my custom preference in it). When i choose some item in ListPreference, i recreate my AudioSamplingSeekBarFragment with chosen data from ListPreference. like this:
public class SettingsFragment extends PreferenceFragment {
private static Logger log = Logger.getLogger(SettingsFragment.class.getName());
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
ListPreference outputFormatPref = (ListPreference) findPreference(getResources().getString(R.string.key_encoder));
outputFormatPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
MySharedPreferences.setAudioEncoder(getActivity(), (String) newValue);
**embedSeekBarWithFormat((String) newValue);**
return true;
}
});
}
**public void embedSeekBarWithFormat(String format) {
try {
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
AudioSamplingSeekBarFragment fragment = (AudioSamplingSeekBarFragment) manager.findFragmentByTag(AudioSamplingSeekBarFragment.TAG);
if (manager.findFragmentByTag(AudioSamplingSeekBarFragment.TAG) != null) {
transaction.remove(fragment);
}
AudioSamplingSeekBarFragment newFragment = new AudioSamplingSeekBarFragment();
Bundle bundle = new Bundle();
bundle.putInt(AudioSamplingSeekBarFragment.STATE_FORMAT, Integer.parseInt(format));
newFragment.setArguments(bundle);
transaction.add(R.id.seekBar_container, newFragment, AudioSamplingSeekBarFragment.TAG);
transaction.commit();
} catch (Exception e) {
log.log(Level.SEVERE, "Exception: ", e);
}
}
}**
So when i quite the SettingActivity and go into again my AudioSamplingSeekBarFragment doesn't save state.
I put my fragment in onSaveInstanceState() in SettingsActivity as they say here: topic
public class SettingsActivity extends android.support.v7.app.ActionBarActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
if (savedInstanceState != null) {
getFragmentManager()
.beginTransaction()
.add(R.id.seekBar_container, getFragmentManager().getFragment(savedInstanceState, AudioSamplingSeekBarFragment.TAG) , AudioSamplingSeekBarFragment.TAG)
.commit();
} else {
getFragmentManager()
.beginTransaction()
.add(R.id.seekBar_container, new AudioSamplingSeekBarFragment(), AudioSamplingSeekBarFragment.TAG)
.commit();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager()
.putFragment(outState, AudioSamplingSeekBarFragment.TAG, getFragmentManager().findFragmentByTag(AudioSamplingSeekBarFragment.TAG));
}
And save specific data in onSaveInstanceState() in Fragment:
public class AudioSamplingSeekBarFragment extends Fragment {
public static final String TAG = "SEEK_BAR_FRAGMENT_TAG";
public static final String STATE_FORMAT = "format";
private int format;
private int seekBarInitVal;
**#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_FORMAT, format);
}**
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_audio_sampling_seekbar, container,false);
}
And i'm expecting to restore saved data here:
#Override
public void onViewCreated(final View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
**format = savedInstanceState.getInt(STATE_FORMAT);**
} else if (getArguments() != null){
format = getArguments().getInt(STATE_FORMAT);
} else {
format = AAC;
}
SeekBar seekBar = (SeekBar)view.findViewById(R.id.sample_rate_seek_bar);
final TextView textProgress = (TextView) view.findViewById(R.id.progress);
switch (format) {
case AAC:
seekBarInitVal = 8000;
seekBar.setMax(40000);
break;
case AAC_ELD:
seekBarInitVal = 16000;
seekBar.setMax(32000);
break;
case AMR_NB:
seekBarInitVal = 8000;
seekBar.setEnabled(false);
break;
case AMR_WB:
seekBarInitVal = 16000;
seekBar.setEnabled(false);
break;
case HE_AAC:
seekBarInitVal = 8000;
seekBar.setMax(40000);
break;
}
textProgress.setText("" + seekBarInitVal + " Hz");
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
i += seekBarInitVal;
textProgress.setText("" + i + " Hz");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
But it doesn't work.
Just in case layouts:
activity_preference:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar"/>
<FrameLayout
android:id="#+id/preferences_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="#+id/seekBar_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
fragment_audio_sampling_seekbar:
<?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:id="#+id/seekBar_fragment">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dbdbdd" />
<TextView
android:id="#+id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="15dp"
android:layout_marginTop="14dp"
android:text="Set Audio Sampling Rate"
android:textAppearance="#style/TextAppearance.AppCompat" />
<SeekBar
android:id="#+id/sample_rate_seek_bar"
android:layout_width="303dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignStart="#+id/summary"
android:layout_marginTop="40dp" />
<TextView
android:id="#+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignStart="#+id/summary"
android:layout_marginTop="66dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginTop="96dp"
android:background="#dbdbdd" />
</RelativeLayout>

As far as I was aware, SavedInstanceState only stores a Bundle of data. Only basic things such as Strings, Integers etc. and does not hold anything like Views.
I think you should really use a ViewModel as it can hold data such as custom classes and views and keep them during orientations changes and are only lost once the Activity is destroyed.
Android View Models
You can then code in a more "permanent" storage option say using SharedPreferences, files, sqlite when the Activity is destroyed. The persisted data can then be fetched and populate the ViewModel in the onAttatch method.
Maybe have a read of this to determine your requirements:
Android - Saving UI states.

Related

NullPointerException: Attempt to invoke virtual method 'void SettingsFragment.loadFromSharedPreferences()' on a null object reference

I try to invoke loadFromSharedPreferences() function from SettingsFragment in MainActivity with fragment variable, but fragment becomes null when I instance it. I tried findFragmentById() and findFragmentByTag() methodes and neither of them worked. Is there another way to do it? Why findFragmentById() methode won't work? I also tried to change FragmentLayout to ConstraintLayout and didn't work.
MainActivity class:
public class MainActivity extends AppCompatActivity {
FragmentManager manager;
SettingsFragment fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//loadFromSharedPreferences()
manager = getSupportFragmentManager();
fragment = (SettingsFragment) manager.findFragmentById(R.id.settingsFragment);
fragment.loadFromSharedPreferences();
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
setTheme(R.style.AppThemeDark);
} else {
setTheme(R.style.AppTheme);
}
setContentView(R.layout.activity_main);
final DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
findViewById(R.id.imageMenu).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view){
drawerLayout.openDrawer(GravityCompat.START);
}
});
NavigationView navigationView = findViewById(R.id.navigationView);
navigationView.setItemIconTintList(null);
NavController navController = Navigation.findNavController(this, R.id.navHostFragment);
NavigationUI.setupWithNavController(navigationView, navController);
final TextView textTitle = findViewById(R.id.textTitle);
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
#Override
public void onDestinationChanged(#NonNull NavController controller, #NonNull NavDestination destination, #Nullable Bundle arguments) {
textTitle.setText(destination.getLabel());
}
});
}
//AppCompatDelegate.setDefaultNightMode will cause your activities to reload automatically
public void ToggleTheme( boolean isChecked ){
if (isChecked) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
else{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
}
SettingsFragment class:
public class SettingsFragment extends Fragment {
public SettingsFragment() {
// Required empty public constructor
}
public static final String SAVE_SWITCH = "saveSwitch";
public static final String IS_CHECKED = "isChecked";
Switch switchTheme;
SharedPreferences sharedPreferences;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_settings, container, false);
switchTheme = (Switch) view.findViewById(R.id.switchMode);
sharedPreferences = getActivity().getApplicationContext()
.getSharedPreferences( SAVE_SWITCH , Context.MODE_PRIVATE);
// loadFromSharedPreferences();
switchTheme.setChecked(sharedPreferences.getBoolean(IS_CHECKED,false));
switchTheme.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
SharedPreferences.Editor editor = sharedPreferences.edit();
//Scriere in fis SharedPreferences
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
editor.putBoolean(IS_CHECKED,true);
switchTheme.setChecked(true);
editor.apply();
((MainActivity) getActivity()).ToggleTheme(isChecked);
}
else{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
editor.putBoolean(IS_CHECKED, false);
switchTheme.setChecked(false);
editor.apply();
((MainActivity) getActivity()).ToggleTheme(isChecked);
}
}
});
return view;
}
//Citire din fis SharedPreferences
public void loadFromSharedPreferences() {
boolean ischecked = sharedPreferences.getBoolean(IS_CHECKED, false);
switchTheme.setChecked(ischecked);
((MainActivity) getActivity()).ToggleTheme(ischecked);
}
}
SettingdFragment XML:
<androidx.constraintlayout.widget.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:id="#+id/settingsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingsFragment"
tools:ignore="MissingClass">
<!-- android:tag="settingsTag"-->
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/textView6"
android:layout_width="113dp"
android:layout_height="49dp"
android:layout_gravity="top"
android:layout_marginStart="131dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="137dp"
android:text="#string/settings"
android:textSize="28sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/tvDarkSide"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tvDarkSide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:text="#string/light_dark_mode"
android:textColor="#F10000"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="#+id/switchMode"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/switchMode" />
<Switch
android:id="#+id/switchMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="110dp"
android:layout_marginEnd="23dp"
android:text="Switch"
android:textSize="18sp"
android:checked="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tvLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="44dp"
android:text="#string/select_the_language"
android:textColor="#F10000"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvDarkSide" />
<Spinner
android:id="#+id/spinnerSelectLanguage"
android:layout_width="370dp"
android:layout_height="22dp"
android:background="?attr/colorBackground"
android:text="Language"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.682"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView6"
app:layout_constraintVertical_bias="0.248" />
</androidx.constraintlayout.widget.ConstraintLayout>
There are several issues with your code.
First of all, the id R.id.settingsFragment does not refer to the fragment itself, but rather the ConstraintLayout that is part of the fragment's layout.
Secondly, you have not created the fragment at all, nor did you add it to your activity, naturally the supportFragmentManager would return null when you attempt to find your fragment.
UPDATE
Your sharedPreferences is null when you call fragment.loadFromSharedPreferences(), that is because the property preferences is initialized in your fragment's onCreateView() function. fragment = new SettingsFragment(); just creates the fragment's instance, it takes time for the fragment's view to finish inflating. Access the preferences only when you are sure it has been initialized. Furthermore, you set your switch's check state on too many (wrong) occasions, which caused looping of the app. The check should be set programatically only once at the creation of the fragment's view, then the check state is changed by user interaction, no reason to change it programatically anywhere else. For your specific code to work, do:
public class SettingsFragment extends Fragment {
public SettingsFragment() {
// Required empty public constructor
}
public static final String SAVE_SWITCH = "saveSwitch";
public static final String IS_CHECKED = "isChecked";
Switch switchTheme;
SharedPreferences sharedPreferences;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_settings, container, false);
switchTheme = (Switch) view.findViewById(R.id.switchMode);
sharedPreferences = getActivity().getSharedPreferences( SAVE_SWITCH , Context.MODE_PRIVATE);
boolean initChecked = sharedPreferences.getBoolean(IS_CHECKED,false);
switchTheme.setChecked(initChecked);
// use clickListener instead. As the activity and the fragment is recreated when the theme is switched,
// the isCheckedListener was called every time as you call switchTheme.setChecked() above. Use clickListener
// to react to user interction only.
switchTheme.setOnClickListener(new View.OnClickListener() {
SharedPreferences.Editor editor = sharedPreferences.edit();
#Override
public void onClick(View view) {
if (switchTheme.isChecked()) {
editor.putBoolean(IS_CHECKED,true);
// editor.apply() may have a delay, editor.commit() saves the changes immediately
editor.commit();
((MainActivity) getActivity()).toggleTheme(true);
}
else{
editor.putBoolean(IS_CHECKED, false);
editor.commit();
((MainActivity) getActivity()).toggleTheme(false);
}
}
});
return view;
}
#Override
public void onDestroyView() {
switchTheme.setOnCheckedChangeListener(null);
super.onDestroyView();
}
// here `onCreateView` has finished, i.e. preferences has been initialized and we can safely access it.
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
boolean isChecked = sharedPreferences.getBoolean(IS_CHECKED, false);
// Then we tell the activity about this event.
((MainActivity) getActivity()).onSettingsFragmentViewCreated(isChecked);
}
}
And for your activity:
...
import android.util.Log;
public class MainActivity extends AppCompatActivity {
FragmentManager manager;
SettingsFragment fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme);
// inflate the activity's view first
setContentView(R.layout.activity_main);
// refer to this activity's fragment manager
manager = getSupportFragmentManager();
// create the fragment first
fragment = new SettingsFragment();
// attach it to this activity's default fragment container using the fragment manager
manager.beginTransaction().add(android.R.id.content, fragment, "SettingsFragment").commit();
}
public void onSettingsFragmentViewCreated(Boolean ischecked) {
// once the preferences are created, you can access them anywhere in the app using the corresponding name
// SharedPreferences sharedPreferences = getSharedPreferences( SAVE_SWITCH , Context.MODE_PRIVATE);
// but in our case we don't need the preferences itself
toggleTheme(ischecked);
}
public void toggleTheme(boolean isChecked ){
// improve conditions to avoid setting the same theme
if (isChecked && AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_YES) {
Log.d("AAAA", "switched to MODE_NIGHT_YES");
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
else if (!isChecked && AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_NO) {
Log.d("AAAA", "switched to MODE_NIGHT_NO");
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
}

Android "No view found for id for fragment"

Okay. I am stuck and having a headache... I am not sure how to access the other layout's view, since inflating does not work.
Here are my codes.
WriteRouteActivity.java
public class WriteRouteActivity extends AppCompatActivity {
private Toolbar tb;
private TextView txt_toolbar_title;
private Button btnSearchPlaces;
private LinearLayout parentLayout, placesCoverLayout;
private View popupView;
private ImageView imgShowPlaces;
private boolean isKeyBoardVisible;
private int keyboardHeight;
private EditText edtSearchPlaces;
private PopupWindow popupWindow;
//popupView
private TabLayout tabLayout;
private FrameLayout frameLayout;
//prework
private int minusVal;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_route);
initView();
}
private void initView() {
//for activity and native back button
tb = (Toolbar) findViewById(R.id.nav_toolbar);
setSupportActionBar(tb);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
txt_toolbar_title = (TextView) findViewById(R.id.txt_toolbar);
parentLayout = (LinearLayout) findViewById(R.id.layout_parent);
placesCoverLayout = (LinearLayout) findViewById(R.id.footer_for_places);
imgShowPlaces = (ImageView) findViewById(R.id.img_show_places);
edtSearchPlaces =(EditText) findViewById(R.id.edt_search_place);
btnSearchPlaces = (Button) findViewById(R.id.btn_search_place);
popupView = getLayoutInflater().inflate(R.layout.places_popup, null);
tabLayout = (TabLayout) popupView.findViewById(R.id.tab_layout);
frameLayout = (FrameLayout) popupView.findViewById(R.id.frame_layout);
doWorkForLayotus();
}
private void doWorkForLayotus(){
final float popUpheight = getResources().getDimension(R.dimen.keyboard_height);
changeKeyboardHeight((int) popUpheight);
enablePopUpView();
setTabLayout();
checkKeyboardHeight(parentLayout);
enableFooterView();
}
public void setCurrentTabFragment(int position) throws IllegalAccessException, InstantiationException {
String tag="";
Fragment fr = null;
Class frClass = null;
FragmentManager frManager = getSupportFragmentManager();
switch (position) {
case 0:
tag = "first";
//hide
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("second")).commit();
}
if(frManager.findFragmentByTag("third")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("third")).commit();
}
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("fourth")).commit();
}
//show
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("first")).commit();
}else{ //add
try {
frManager.beginTransaction().add(frameLayout.getId(), ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}catch(Exception e){
Log.e("why", e.getMessage().toString());
}
}
break;
case 1:
tag = "second";
//hide
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("first")).commit();
}
if(frManager.findFragmentByTag("third")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("third")).commit();
}
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("fourth")).commit();
}
//show
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("second")).commit();
}else{ //add
frManager.beginTransaction().add(frameLayout.getId(), ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}
break;
case 2:
tag = "third";
//hide
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("first")).commit();
}
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("second")).commit();
}
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("fourth")).commit();
}
//show
if(frManager.findFragmentByTag("third")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("third")).commit();
}else{ //add
frManager.beginTransaction().add(frameLayout.getId(), ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}
break;
case 3:
tag = "fourth";
//hide
if(frManager.findFragmentByTag("first")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("first")).commit();
}
if(frManager.findFragmentByTag("second")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("second")).commit();
}
if(frManager.findFramentByTag("third")!=null){
frManager.beginTransaction().hide(frManager.findFragmentByTag("third")).commit();
}
//show
if(frManager.findFragmentByTag("fourth")!=null){
frManager.beginTransaction().show(frManager.findFragmentByTag("fourth")).commit();
}else{ //add
frManager.beginTransaction().add(R.id.frame_layout, ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
}
break;
}
//frManager.beginTransaction().replace(R.id.frame_container, fr, tag).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
}
private void setTabLayout(){
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
try {
setCurrentTabFragment(tab.getPosition());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void enablePopUpView() {
// Creating a pop window for emoticons keyboard
popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT,
(int) keyboardHeight, false);
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
placesCoverLayout.setVisibility(LinearLayout.GONE);
}
});
}
int previousHeightDiffrence = 0;
private void checkKeyboardHeight(final View parentLayout) {
parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
parentLayout.getWindowVisibleDisplayFrame(r);
int screenHeight = parentLayout.getRootView()
.getHeight();
minusVal=screenHeight-r.bottom;
int heightDifference = screenHeight - (r.bottom+(minusVal));
if (previousHeightDiffrence - heightDifference > 50) {
popupWindow.dismiss();
}
previousHeightDiffrence = heightDifference;
if (heightDifference > 100) {
isKeyBoardVisible = true;
changeKeyboardHeight(heightDifference);
} else {
isKeyBoardVisible = false;
}
}
});
}
private void changeKeyboardHeight(int height) {
if (height > 100) {
keyboardHeight = height;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, keyboardHeight);
placesCoverLayout.setLayoutParams(params);
}
}
private void enableFooterView() {
edtSearchPlaces.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (popupWindow.isShowing()) {
popupWindow.dismiss();
}
}
});
btnSearchPlaces.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
hideSoftKeyboard(WriteRouteActivity.this);
if(!popupWindow.isShowing()){
popupWindow.setHeight((int) (keyboardHeight));
if (isKeyBoardVisible) {
placesCoverLayout.setVisibility(LinearLayout.GONE);
} else {
placesCoverLayout.setVisibility(LinearLayout.VISIBLE);
}
popupWindow.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
popupWindow.showAtLocation(parentLayout, Gravity.BOTTOM, 0, 0);
try {
setCurrentTabFragment(0);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} else {
//popupWindow.dismiss();
}
}
});
}
#Override
protected void onDestroy() {
popupWindow.dismiss();
super.onDestroy();
}
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
#Override
public void onBackPressed() {
if(popupWindow.isShowing()){
popupWindow.dismiss();
}else {
super.onBackPressed();
}
}
}
activity_write_wroute.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/nav_toolbar" />
<fragment
android:id="#+id/google_map"
class="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include
android:id="#+id/footer_layout"
layout="#layout/footer_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/footer_for_places"
android:layout_width="match_parent"
android:layout_height="#dimen/keyboard_height"
android:background="#android:color/transparent"
android:orientation="vertical"
android:visibility="gone" />
</LinearLayout>
Fragment_Zasin
public class Fragment_zasin extends Fragment {
public Fragment_zasin newInstance() {
Fragment_zasin fr = new Fragment_zasin();
return fr;
}
public Fragment_zasin() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_zasin, container, false);
return rootView;
}
}
places_popup.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/linear_layout_top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="fill_parent"
android:layout_height="?attr/actionBarSize"
android:background="#ffffff"
app:tabGravity="fill"
app:tabIndicatorColor="#color/colorPrimary"
app:tabIndicatorHeight="4dp"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorPrimary">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_pin_selector"
android:text="11">
</android.support.design.widget.TabItem>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_mainroute_selector"
android:text="22" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_talk_selector"
android:text="33" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/tab_my_selector"
android:text="44" />
</android.support.design.widget.TabLayout>
<FrameLayout
android:id="#+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
LOGCAT Message
FATAL EXCEPTION: main Process: suacuration.itgotravel, PID: 20131
java.lang.IllegalArgumentException: No view found for id 0x7f100173 for fragment Fragment_zasin{d4ac39c #0 id=0x7f100173 first}
Can somebody help this?
This error occurs because the fragment manager could not find the view on which it has to inflate the fragment.
The fragment transaction is linked to the activity so this error occurs as the frame layout is not a part of that main activity's xml.so it cant find where to add the fragment.fragment has to be added inside the activity.
what you have to do is provide the id of a view in your main activity.
for e.g your main view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mainView"//like this
android:orientation="vertical">
<include layout="#layout/nav_toolbar" />
<fragment
android:id="#+id/google_map"
class="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include
android:id="#+id/footer_layout"
layout="#layout/footer_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/footer_for_places"
android:layout_width="match_parent"
android:layout_height="#dimen/keyboard_height"
android:background="#android:color/transparent"
android:orientation="vertical"
android:visibility="gone" />
</LinearLayout>
The view where you are trying to inflate the fragemnt must be inside activity.
Now when you try
frManager.beginTransaction().add(R.id.mainView, ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
the fragment will be loaded on this view of your activity.
Problem is you are trying to show a Fragment on a View which is not defined in your layout which you have defined in your onCreate() while setContentView(layoutId)
In your case you are inflating fragments in WriteRouteActivity where layout defined is activity_write_route and fragments are added on FrameLayout which is defined in places_popup.xml so define your framelayout in a view layout of Activity.
Small Description :
--------code------
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-------layout define for activity-------
setContentView(R.layout.activity_write_route);
}
now where you are adding fragment on a FrameLayout(view)
frManager.beginTransaction().add(R.id.frame_layout, ((Fragment) Fragment_zasin.class.newInstance()), tag).commit();
here R.id.frame_layout should be define in your layout activity_write_route.
Okay i found an answer.
The problem was that fragment cannot be a child of a 'Dialog'.
Since i used popup dialog, it was unable to put fragments inside the dialog.
i solved by inflating views rather than using fragments in tablayout.
There could be other errors but what is this?
tb = (Toolbar) findViewById(R.id.nav_toolbar);
This is not a toolbar:
<include layout="#layout/nav_toolbar" />
Can we see inside this nav_toolbar layout?
Also, where is this: "R.layout.fragment_zasin". It's complaining about a Fragment so it would be worthwhile seeing if this is ok.
Anyway, as a general troubleshooting strategy, try commenting out all those lines in the initView() method and just add them in one at a time until it fails. Or maybe if you scroll down in the error logs further it will give you a hyperlink to the line that's causing it to fail.
Why do you have "frameLayout.getId()" on one line but "R.id.frame_layout" on another? Try to use the latter for all of the lines and see if that's it.
I was extending the wrong type of activity, extended AppCompact solved issue.
Got this error when starting new fragment from fragment, using ChildFragmentManager, and giving id of container from activity, in transaction replace method.
It happens that FragmentManager has access to activity containers, but ChildFragmentManager has access to fragment containers.
The solution was to use FragmentManager class instead of ChildFragmentManager.
You got this error because your view found for id 0x7f100173 into fragment Fragment_zasin so only solution is that:
1) check all id present to that particular layout.
2) if all id is present to that particular layout and still you facing same issue do one thing change name of id don't refactor change name and access this changed id name in your fragment or activity.

ShowcaseView - width and height must be > 0

Research has been fruitless because all other references to this error seem to be reliably repeatable; I'm unable to consistently repeat this error:
08-22 17:32:25.216 22699-22699/com.smbds.punisher11 E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalArgumentException: width and height must be > 0
at android.graphics.Bitmap.createBitmap(Bitmap.java:1023)
at android.graphics.Bitmap.createBitmap(Bitmap.java:1002)
at android.graphics.Bitmap.createBitmap(Bitmap.java:985)
at com.github.amlcurran.showcaseview.ShowcaseView.updateBitmap(ShowcaseView.java:171)
at com.github.amlcurran.showcaseview.ShowcaseView.onGlobalLayout(ShowcaseView.java:354)
at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:655)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2054)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1190)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4860)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:766)
at android.view.Choreographer.doCallbacks(Choreographer.java:575)
at android.view.Choreographer.doFrame(Choreographer.java:542)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:751)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:5751)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1083)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:850)
at dalvik.system.NativeStart.main(Native Method)
As I stated above, this error does not occur all the time. It seems to happen about (but not exactly) 2-3 times, then 2-3 runs go through without a problem.
Here is my resources file:
<?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/container_fragment_person_list"
android:tag="PersonListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.PersonListFragment">
<TextView
android:id="#+id/textView_add_guardian_placeholder"
android:layout_centerInParent="true"
android:layout_width="1dp"
android:layout_height="1dp" />
<TextView
android:id="#+id/textView_intro_placeholder"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:minWidth="1dp"
android:minHeight="1dp"
android:layout_width="1dp"
android:layout_height="1dp" />
<ListView
android:visibility="gone"
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:orientation="vertical"
android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<TextView
android:text="#string/no_people"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageButton
android:id="#+id/imageButton_empty_text"
android:src="#drawable/ic_man_silhouette_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/generic_content_description"/>
<TextView
android:id="#+id/test"
android:text="#string/tap_icon_to_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
And here is my java. Please notice that I even tried hard-coding a width and height for my ViewTarget, but still get inconsistent errors. I also tried creating placeholder TextViews in my resources file, but still no go.
public class PersonListFragment extends BaseListFragment {
private PersonAdapter personAdapter;
private PersonModel personModel;
private int personCount;
private TextView tvTargetIntro;
public static PersonListFragment newInstance(String tag, Long index) {
PersonListFragment fragment = new PersonListFragment();
Bundle args = new Bundle();
args.putString(TAG, tag);
args.putLong(INDEX, index);
fragment.setArguments(args);
return fragment;
}
public PersonListFragment() {
}
#SuppressWarnings("UnusedDeclaration")
public void onEventMainThread(People_FetchedEvent ignored) {
refreshList();
}
#SuppressWarnings("UnusedDeclaration")
public void onEventMainThread(Person_CreatedEvent ignored) {
String createType;
if(ignored.getId() == 0 | ignored.getPerson().getId() == null) {
createType = resources.getString(R.string.added);
} else {
createType = resources.getString(R.string.updated);
}
MessageManager.getInstance().makeToast(getActivity(), ignored.getPerson().getName(), " ", createType);
fm.popBackStack();
refreshList();
}
#SuppressWarnings("UnusedDeclaration")
public void onEventMainThread(Person_BuiltEvent ignored) {
makeCreatePersonBackgroundTask(ignored.getPerson());
}
#SuppressWarnings("UnusedDeclaration")
public void onEventMainThread(Person_DeletingEvent ignored) {
personModel.deletePersonByLocalId(ignored.getId());
MessageManager.getInstance().makeToast(getActivity(), PersonController.getInstance().getCurrentPerson().getName() + " " + resources.getString(R.string.removed));
refreshList();
FragmentManager fm = getChildFragmentManager();
fm.popBackStack();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
personModel = PersonModel.getInstance();
personAdapter = new PersonAdapter(getActivity().getLayoutInflater(), getActivity(), ListType.PROFILE_INFO);
setListAdapter(personAdapter);
personCount = PersonModel.getInstance().getPersonCount();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_person_list, container, false);
LinearLayout layoutEmptyList = (LinearLayout) view.findViewById(android.R.id.empty);
tvTargetIntro = (TextView) view.findViewById(R.id.textView_intro_placeholder);
ImageButton imageButtonEmptyText = (ImageButton) view.findViewById(R.id.imageButton_empty_text);
imageButtonEmptyText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction ft;
ft = fm.beginTransaction();
ft.replace(R.id.container_fragment_person_list, PersonEditFragment.newInstance("PERSON_EDIT_FRAGMENT", (long) 0, new Person()), "PERSON_EDIT_FRAGMENT");
ft.addToBackStack(null);
ft.commit();
fm.executePendingTransactions();
}
});
switch(personCount) {
case 0:
break;
case 1:
break;
default:
}
return view;
}
private void makeShowCaseIntro() {
ViewTarget target1 = new ViewTarget(tvTargetIntro);
tvTargetIntro.setWidth(1);
tvTargetIntro.setHeight(1);
ShowcaseView sv = new ShowcaseView.Builder(getActivity())
.setTarget(target1)
.setContentTitle(resources.getString(R.string.showcase_intro_title))
.setContentText(resources.getString(R.string.showcase_intro_text))
.setStyle(R.style.CustomShowcaseTheme2)
.build();
sv.setButtonText(resources.getString(R.string.next));
sv.show();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
makeShowCaseIntro();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
PersonController.getInstance().setCurrentPerson(personAdapter.getItem(position));
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container_fragment_person_list, PersonDisplayFragment.newInstance("PERSON_DISPLAY_FRAGMENT", PersonController.getInstance().getLocalId(), PersonController.getInstance().getCurrentPerson()), "PERSON_DISPLAY_FRAGMENT");
ft.addToBackStack(null);
ft.commit();
fm.executePendingTransactions();
}
private void refreshList() {
new SimpleBackgroundTask<LazyList<Person>>(getActivity()) {
#Override
protected LazyList<Person> onRun() {
return PersonModel.getInstance().lazyLoadPeople();
}
#Override
protected void onSuccess(LazyList<Person> result) {
personAdapter.replaceLazyList(result);
}
}.execute();
}
private void makeCreatePersonBackgroundTask(Person person) {
jobManager.addJobInBackground(new CreatePersonJob(person));
fm.popBackStack();
}
#Override
public void onResume() {
super.onResume();
jobManager.addJobInBackground(new FetchPeopleJob());
if(dataDirty) {
refreshList();
dataDirty = false;
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
FragmentTransaction ft;
Person person = PersonController.getInstance().getCurrentPerson();
ft = fm.beginTransaction();
switch(item.getItemId()) {
case R.id.action_new:
ft.replace(R.id.container_fragment_person_list, PersonEditFragment.newInstance("PERSON_EDIT_FRAGMENT", (long) 0, new Person()), "PERSON_EDIT_FRAGMENT");
ft.addToBackStack(null);
ft.commit();
fm.executePendingTransactions();
return true;
case R.id.action_edit:
ft.replace(R.id.container_fragment_person_list, PersonEditFragment.newInstance("PERSON_EDIT_FRAGMENT", person.getId(), person), "PERSON_EDIT_FRAGMENT");
ft.addToBackStack(null);
ft.commit();
fm.executePendingTransactions();
return true;
case R.id.action_remove:
String title = MessageManager.getInstance().makeString(resources.getString(R.string.remove), " ", person.getName());
String message = MessageManager.getInstance().makeString(resources.getString(R.string.message_confirm_remove), " ", person.getName(), resources.getString(R.string.punctuation_question));
final InfoDialogFragment dialog = InfoDialogFragment.newInstance(title, message, DialogActionType.Delete, DialogActionTarget.Person, person.getId());
dialog.show(ft, DIALOG_TAG);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
I'm pretty sure this is some timing issue with the way android draws out objects, but I don't have the knowledge to know why they're drawn correctly on some runs but not on others.
Please don't zap this question unless you're sure that it has been asked elsewhere with respect to an intermittent problem :-)
Any help is appreciated.
This is a known issue : Github issues when updateBitmap() is called too early.
This issue comes from Bitmap.createBitmap() method either width or height equals to 0.
A workaround is to delay the ShowcaseView creation more:
someView.post(new Runnable() {
#Override
public void run() {
// display ShowcaseView here
}
});
You could also change the updateBitmap() method from the library to not create the bitmap if the view width or height is wrong.
Had the same problem, and posted my solution in another thread:
https://stackoverflow.com/a/25521608/1752670
I changed the ShowcaseView class slightly
go to com.github.amlcurran.showcaseview.ShowcaseView and change this method
private void updateBitmap() {
if ((bitmapBuffer == null || haveBoundsChanged()) && getMeasuredHeight() > 0 && getMeasuredWidth() > 0) {
if(bitmapBuffer != null)
bitmapBuffer.recycle();
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if(width > 0 && height > 0)
bitmapBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
}
This was a bug in ShowcaseView, and was fixed starting in v5.4.2:
https://github.com/amlcurran/ShowcaseView/commit/c79c60dc798f081fb62e48c549c7bdbff8da51b9
So, you can just update your build.gradle to:
compile 'com.github.amlcurran.showcaseview:library:5.4.2'

Get edittext value from fragment

I am using fragments,I have an edittext in fragment and I want to get value in main activity.
This is my fragment layout
<?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:orientation="vertical"
android:background="#878787" >
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="dfgdfgdf"
android:textSize="20dp"
android:layout_centerInParent="true"
android:id="#+id/user_name"/>
<EditText
android:id="#+id/message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:text="Gönder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="getFromUser"
android:layout_marginTop="40dp"
/>
</RelativeLayout>
I am loading fragment with this function:
public void startChat(JsonObject user) {
FrameLayout layout = (FrameLayout)findViewById(R.id.container);
layout.setVisibility(View.VISIBLE);
Bundle bundle = new Bundle();
bundle.putString("name", user.get("name").getAsString());
sendTo=user.get("username").getAsString();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ConversationFragment conv = new ConversationFragment();
conv.setArguments(bundle);
fragmentTransaction.add(R.id.container, conv);
fragmentTransaction.commit();
viewPager.setVisibility(View.GONE);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayHomeAsUpEnabled(true);
}
And this is my fragment class
public class ConversationFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String name = getArguments().getString("name");
View rootView = inflater.inflate(R.layout.fragment_conversation, container, false);
TextView username=(TextView)rootView.findViewById(R.id.user_name);
username.setText(name);
return rootView;
}
}
As you can see when press the button main activity runs "getFromUser" function.I want to get edittext value in this function.How can I do this ?
It's always the same procedure for these things. You can't access a fragment's views just like that. You need a callback method.
Add this code to ConversationFragment:
private OnGetFromUserClickListener mListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnGetFromUserClickListener ) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnGetFromUserClickListener");
}
}
public void getFromUser(View v) {
if (mListener != null) {
EditText edit = (EditText)findViewById(R.id.message);
mListener.getFromUser(edit.getText().toString());
}
}
public interface OnGetFromUserClickListener {
void getFromUser(String message);
}
Make your MainActivity implement this interface. Replace getFromUser() inside MainActivity with:
public void getFromUser(String message) {
sendMessage(message);
}
Done.
Edit:
Actually, using the XML-onClick attribute is currently bugged (see onClick inside fragment called on Activity): It links to the activity instead of the fragment. You have to set the click listener programmatically to make sure the code won't break at some point in the future. So give the button an ID inside the XML (e.g. get_from_user) and add this code to onCreateView inside ConversationFragment:
v.findViewById(R.id.get_from_user).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (v.getId() == R.id.get_from_user) {
getFromUser(v);
}
}
});
Using this code vastly decouples the activity and the fragment from each other.
I resolved this problem.
public void getFromUser(View view) {
ConversationFragment fragment1 = (ConversationFragment)getSupportFragmentManager().findFragmentById(R.id.container);
View frag=fragment1.getView();
EditText editText1 =(EditText) frag.findViewById(R.id.message);
String message=editText1.getText().toString();
sendMessage(message);
}
Now I can get edittext value from fragment.

Accessing Views inside fragment

I'm having troubles accessing the Views that within my Fragment. In the example below, I can't access the 2nd button that is within the Fragment (e.g., findViewById appears to return NULL and the app crashes when I try b2.setText("test") ), but when I directly add it in the activity_main.xml, it does work.
Here is the code:
MainActivity.java
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button fragmentButton = (Button)findViewById(R.id.iMainButton);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.iMainInnerLLContainer, new TestFragment());
ft.commit();
final Button b2 = (Button)findViewById(R.id.iTestFragmentInnerButton);
if(b2 == null) { Log.d("MainActivity.java:", "b2 is null"); }
else { Log.d("MainActivity.java:", "b2 is NOT null"); }
fragmentButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// do stuff here
}
});
}
}
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:id="#+id/iMainRootLinearLayoutContainer"
android:orientation="vertical"
>
<Button
android:id="#+id/iMainButton"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Add fragment..."
/>
<LinearLayout
android:id="#+id/iMainInnerLLContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
>
<!-- Fragment goes here, can reference button if it is added here manually -->
</LinearLayout>
</LinearLayout>
TestFragment.java
public class TestFragment extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.ltestfragment, container, false);
}
}
ltestfragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/iTestFragmentOuterLinearLayout"
>
<Button
android:id="#+id/iTestFragmentInnerButton"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="This is my test fragment button."
/>
</LinearLayout>
I think I'm missing something very basic here and I would appreciate some insight on what that might be.
Thank you in advance!
I think you need to set up a textchangelistener in your fragment.
public class FragmentA extends Fragment {
TextChangeListener listener;
public interface TextChangeListener {
public void onTextChange(CharSequence newText);
}
public void setTextChangeListener(TextChangeListener listener) {
this.listener = listener;
}
Then, in your activity, set up the listener :
public class ActivityAB extends FragmentActivity {
FragmentA fragmentA;
FragmentB fragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ab);
FragmentManager manager = getSupportFragmentManager();
fragmentA = (FragmentA) manager.findFragmentById(R.id.fragmentA);
fragmentB = (FragmentB) manager.findFragmentById(R.id.fragmentB);
fragmentA.setTextChangeListener(new TextChangeListener() {
#Override
public void onTextChange(CharSequence newText) {
fragmentB.updateTextValue(newText);
}
});
}
}
Implement an interface to listen to the events of a fragment from its activity.
Code in Fragment:-
public class TestFragment extends Fragment
{
public interface OnClickListener
{
public void onButtonClicked(<data type><data>);
}
b2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
listener.onButtonClicked(<<pass some values here>>);
}
});
}
Code in Main:-
MainActivity extends FragmentActivity implements TestFragment.OnClickListener,
{
#Override
public void onButtonClicked(<<receive the pased data here>>) {
//do some stuff here with the received data after the button is clicked
}
}

Categories

Resources