How to open a Fragment on click from a fragment in Android - android

Firstly I'm new to android and sorry for my english.
I have an application where I display images, in it I use a grid with image gallery.
Now I need to make a gallery of images with Gif, so I found this project. LINK
My project uses Fragmets I am trying to convert this project above in mine, however I am having problems in the call Activity.
The initial project activity looks like this:
package com.tenor.android.demo.search.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.tenor.android.core.constant.StringConstant;
import com.tenor.android.core.model.impl.Tag;
import com.tenor.android.core.response.BaseError;
import com.tenor.android.core.util.AbstractUIUtils;
import com.tenor.android.core.widget.adapter.AbstractRVItem;
import com.tenor.android.demo.search.R;
import com.tenor.android.demo.search.adapter.TagsAdapter;
import com.tenor.android.demo.search.adapter.decorations.MainTagsItemDecoration;
import com.tenor.android.demo.search.adapter.rvitem.TagRVItem;
import com.tenor.android.demo.search.adapter.view.IMainView;
import com.tenor.android.demo.search.presenter.IMainPresenter;
import com.tenor.android.demo.search.presenter.impl.MainPresenter;
import com.tenor.android.demo.search.widget.TenorStaggeredGridLayoutManager;
import java.util.ArrayList;
import java.util.List;
/**
* For the MainActivity, we will display a search bar followed by a stream of Tags pulled from the Tenor API.
* Either by clicking on a tag or entering a search, SearchActivity will open.
*/
public class MainActivity extends AppCompatActivity implements IMainView{
// Number of columns for the RecyclerView
private static final int STAGGERED_GRID_LAYOUT_COLUMN_NUMBER = 2;
// Minimum length a search term can be
private static final int TEXT_QUERY_MIN_LENGTH = 2;
// A search box for entering a search term
public EditText mEditText;
// RecyclerView to display the stream of Tags
public RecyclerView mRecyclerView;
// Api calls for MainActivity performed here
private IMainPresenter mPresenter;
// Adapter containing the tag items/view holders
private TagsAdapter mTagsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = (EditText) findViewById(R.id.am_et_search);
mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
final String query = textView.getText().toString().trim();
if (query.length() < TEXT_QUERY_MIN_LENGTH) {
Toast.makeText(MainActivity.this, getString(R.string.search_error), Toast.LENGTH_LONG).show();
return true;
}
// The keyboard enter will perform the search
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
startSearch(query);
return true;
}
return false;
}
});
mRecyclerView = (RecyclerView) findViewById(R.id.am_rv_tags);
mRecyclerView.addItemDecoration(new MainTagsItemDecoration(getContext(), AbstractUIUtils.dpToPx(this, 2)));
// Two column, vertical display
final TenorStaggeredGridLayoutManager layoutManager = new TenorStaggeredGridLayoutManager(STAGGERED_GRID_LAYOUT_COLUMN_NUMBER,
StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mTagsAdapter = new TagsAdapter<>(this);
mRecyclerView.setAdapter(mTagsAdapter);
mPresenter = new MainPresenter(this);
mPresenter.getTags(getContext(), null);
}
private void startSearch(#Nullable final CharSequence text) {
final String query = !TextUtils.isEmpty(text) ? text.toString().trim() : StringConstant.EMPTY;
Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(SearchActivity.KEY_QUERY, query);
startActivity(intent);
}
#Override
public Context getContext() {
return getBaseContext();
}
#Override
public void onReceiveReactionsSucceeded(List<Tag> tags) {
// Map the tags into a list of TagRVItem for the mTagsAdapter
List<AbstractRVItem> list = new ArrayList<>();
for (Tag tag : tags) {
list.add(new TagRVItem(TagsAdapter.TYPE_REACTION_ITEM, tag));
}
mTagsAdapter.insert(list, false);
}
#Override
public void onReceiveReactionsFailed(BaseError error) {
// For now, we will just display nothing if the tags fail to return
}
}
Here my first change:
Note that I changed the class name to not conflict with my MainActivity
public class MainActivityGif extends Fragment implements IMainView {
And here
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//setContentView(R.layout.activity_main_gif);
View view = inflater.inflate(R.layout.activity_main_gif, container, false);
How can I call a fragment within another fragment?
private void startSearch(#Nullable final CharSequence text) {
final String query = !TextUtils.isEmpty(text) ? text.toString().trim() : StringConstant.EMPTY;
Intent intent = new Intent(getActivity(), SearchActivity.class);
intent.putExtra(SearchActivity.KEY_QUERY, query);
MainActivityGif.this.startActivity(intent);
}
If I miss the way to ask, I'm sorry, let me understand where I went wrong.

private FragmentManager mFragmentManager;
private FragmentTransaction mFragmentTransaction;
and inside your onCreate
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
and on click call :
FragmentB fragment = new FragmentB ();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.contentFragment, fragment );
mFragmentTransaction.commit();

Related

RecyclerView of Button array - How to update the data?

This is my first Q on the site, I'll try to form it well.
I have a recyclerView, and the Item is an array of buttons.
Button click shows a popup menu that allows the user to change the color of the button.
I've managed to set that the onClick method will change the color, but I'm clueless about how to save the chosen color in the ButtonArrayList, that Holds the colors.
The problem is that when the button is pressed, I don't know how to understand programatically on which button, in which button array it was pressed.
Thanks!
Just to demonstrate the problem. when button is clicked, How to identify which button of which item was clicked?
1
The code of the fragment:
package com.examples.recyclerViewWithButtonArray;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.LinkedList;
/**
* A simple {#link Fragment} subclass.
* Use the {#link Game#newInstance} factory method to
* create an instance of this fragment.
*/
public class Game extends Fragment {
// TODO: Rename parameter arguments, choose names that match
protected static int[] mButtonsColors;
private final LinkedList<ButtonArray> mButtonArrayList = new LinkedList<>();
RecyclerView mGuessLinesRecyclerView;
ButtonArrayListAdapter mButtonArrayListAdapter;
FloatingActionButton mFab;
// TODO: Rename and change types of parameters
public Game() {
// Required empty public constructor
}
public static Game newInstance(String param1, String param2) {
Game fragment = new Game();
return fragment;
}
private void initGameColors(){
mButtonsColors = new int[4];
int[] c = getContext().getResources().getIntArray(R.array.buttonColors);
//asign colors
for (int i = 0; i < 4; i++) {
this.mButtonsColors[i] = c[i];
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initGameColors();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View vw = inflater.inflate(R.layout.fragment_game, container, false);
return vw;
}
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mGuessLinesRecyclerView = view.findViewById(R.id.recycler_view);
mFab = view.findViewById(R.id.fab);
//initialize recyclerView
// Create an adapter and supply the data to be displayed.
mButtonArrayListAdapter = new ButtonArrayListAdapter(getContext(), mButtonArrayList, this);
// Connect the adapter with the RecyclerView.
mGuessLinesRecyclerView.setAdapter(mButtonArrayListAdapter);
// Give the RecyclerView a default layout manager.
mGuessLinesRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
//initializeFAB
mFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mButtonArrayList.add(new ButtonArray(getContext(),mButtonsColors));
mGuessLinesRecyclerView.setAdapter(mButtonArrayListAdapter);
}
});
//add first array to the recycler view.
// Next guess lines will be added when clicking on movableFab
mButtonArrayList.add(new ButtonArray(getContext(), this.mButtonsColors));
}
}
The code of ButtonArrayListAdapter:
package com.examples.recyclerViewWithButtonArray;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class ButtonArrayListAdapter extends RecyclerView.Adapter<ButtonArrayListAdapter.ButtonArrayViewHolder> {
private final Context mContext;
private final List<ButtonArray> mData;
class ButtonArrayViewHolder extends RecyclerView.ViewHolder {
public ArrayList<Button> mButtons;
final ButtonArrayListAdapter mAdapter;
public ButtonArrayViewHolder(#NonNull View itemView, ButtonArrayListAdapter adapter) {
super(itemView);
this.mAdapter = adapter;
mButtons =new ArrayList<>();
if(4==4)
{
//create an array of button for binding
mButtons.add((Button)itemView.findViewById(R.id.button_Guess1));
mButtons.add((Button)itemView.findViewById(R.id.button_Guess2));
mButtons.add((Button)itemView.findViewById(R.id.button_Guess3));
mButtons.add((Button)itemView.findViewById(R.id.button_Guess4));
}
}
}
public ButtonArrayListAdapter(Context mContext, List<ButtonArray> mData, Game mGame) {
this.mContext = mContext;
this.mData = mData;
}
#NonNull
#Override
public ButtonArrayViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View layout;
layout = LayoutInflater.from(mContext).inflate(R.layout.guess_line,parent,false);
return new ButtonArrayViewHolder(layout,this);
}
#Override
public void onBindViewHolder(#NonNull final ButtonArrayViewHolder buttonArrayViewHolder, final int position) {
//bind data here
//initiate each guessLineButton
for (int i = 0; i < 4; i++) {
int c = mData.get(position).mAnswerButtonsColors[i];
final Button bt = buttonArrayViewHolder.mButtons.get(i);
//set initial button color
bt.setBackgroundColor(c);
//set button clik to open color chooser
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int[] chooseColorButtons = new int[4];
// inflate the layout of the popup window
final View popupView = LayoutInflater.from(mContext).inflate(R.layout.choose_color_popup,null);
// create the popup window
int width = bt.getWidth();
int height = LinearLayout.LayoutParams.WRAP_CONTENT;
boolean focusable = true; // lets taps outside the popup also dismiss it
final PopupWindow popupWindow = new PopupWindow(popupView, width, height, focusable);
// show the popup window
// which view you pass in doesn't matter, it is only used for the window tolken
int[] loc = new int[]{0,0};
bt.getLocationOnScreen(loc);
popupWindow.showAtLocation(v, Gravity.TOP|Gravity.LEFT, loc[0], loc[1] + bt.getHeight());
// dismiss the popup window when touched
popupView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
popupWindow.dismiss();
return true;
}
});
//initiate each color choose button
if(chooseColorButtons.length==4) {
chooseColorButtons[0] = R.id.buttonColor1;
chooseColorButtons[1] = R.id.buttonColor2;
chooseColorButtons[2] = R.id.buttonColor3;
chooseColorButtons[3] = R.id.buttonColor4;
}
for (int j = 0; j < 4 ; j++) {
Button colbt = (Button)(popupView.findViewById(chooseColorButtons[j]));
colbt.setBackgroundColor(Game.mButtonsColors[j]);
colbt.setTextColor(Game.mButtonsColors[j]);
colbt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bt.setBackgroundColor(((ColorDrawable)(((Button)v).getBackground())).getColor());
//WHAT SHOULD I DO HERE?
popupWindow.dismiss();
}
});
}
}
});
}
}
#Override
public int getItemCount() {
return mData.size();
}
}
After reading your question what I get is you want to save the color against every button so next time when that button click the same color should load if yes then you can consider these tw0 suggestions
1- if the number of buttons is static and you are not adding them dynamically then you can hardcode the color against each button by adding them in the list and assign them manually against each button.
2- you can use key-value pair(hash map), these are the best solution for any case either you're are manually adding the button or dynamically, just store the color against each key. In this case, buttons should be your keys and colors will be value.
Thanku

Error in addSlide method in appintro in android studio

There is an error in this line:
addSlide(AppIntroSampleSlider.newInstance(R.layout.app_intro1));
addSlide (android.support.v4.app.Fragment)
In AppIntroBase, it cannot be applied
My code is here:
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import com.github.paolorotolo.appintro.AppIntro;
/**
* Created by Arvind on 2/6/2017.
*/
public class MyIntro extends AppIntro {
#Override
public void init(Bundle savedInstanceState) {
//adding the three slides for introduction app you can ad as many you needed
addSlide(AppIntroSampleSlider.newInstance(R.layout.app_intro1));
addSlide(AppIntroSampleSlider.newInstance(R.layout.app_intro2));
addSlide(AppIntroSampleSlider.newInstance(R.layout.app_intro3));
// Show and Hide Skip and Done buttons
showStatusBar(false);
showSkipButton(false);
// Turn vibration on and set intensity
// You will need to add VIBRATE permission in Manifest file
setVibrate(true);
setVibrateIntensity(30);
//Add animation to the intro slider
setDepthAnimation();
}
#Override
public void onSkipPressed() {
// Do something here when users click or tap on Skip button.
Toast.makeText(getApplicationContext(),
getString(R.string.app_intro_skip), Toast.LENGTH_SHORT).show();
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
}
#Override
public void onNextPressed() {
// Do something here when users click or tap on Next button.
}
#Override
public void onDonePressed() {
// Do something here when users click or tap tap on Done button.
finish();
}
#Override
public void onSlideChanged() {
// Do something here when slide is changed
}
}
I created a class i.e. AppIntroSampleSlider.
My AppIntroSampleSlider class is:
package com.example.arvind.appintro1;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by Arvind on 13-Feb-17.
*/
public class AppIntroSampleSlider extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
public static AppIntroSampleSlider newInstance(int layoutResId) {
AppIntroSampleSlider sampleSlide = new AppIntroSampleSlider();
Bundle bundleArgs = new Bundle();
bundleArgs.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(bundleArgs);
return sampleSlide;
}
private int layoutResId;
public AppIntroSampleSlider() {}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID))
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(layoutResId, container, false);
}
}
I want to why it is showing error in the code.So Please help me to solve this error.
I found a better example without error
http://www.androidhive.info/2016/05/android-build-intro-slider-app/
AppIntro library works best with the following import in your AppIntroSampleSlider.java file:
import android.support.v4.app.Fragment;
Instead of:
import android.app.Fragment;

in viewPager's fragment, recyclerView adapter notifyDataSetChanged not works on first time

I have fragment view pager in activity, that creates a number of pages of entered number before. In each fragment, i have recycler view that needs to update each time user moves to the relevant page. on resume() of each fragment I have getter of data from main activity.
What I am experiencing is while I'm going to next page first time it's not updated, but if after some page movements I would back to it, it is updated, with same resume() code.
I tried some delays after updating the data, it didn't help.
So if before updating data I would check every page it would work as I planned, but if the page was not created before (due to pager adapter) but I still use the same code for updating, it does not work.
I would be glad for some help, stacked on it for 2 days already.
Main Activity:
package com.slavafleer.tipcalculator02;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import com.slavafleer.tipcalculator02.recycler.PageHeaderAdapter;
import java.util.ArrayList;
public class ManualModeActivity extends AppCompatActivity implements
PageHeaderAdapter.Callbacks, DinerFragment.Callbacks {
private int mDinersAmount;
private ViewPager mViewPagerDiners;
private PageHeaderAdapter mHeaderAdapter;
private DinersPagerAdapter mDinersPagerAdapter;
private ArrayList<Order> mOrders;
public ArrayList<Order> getOrders() {
return mOrders;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manual_mode);
mOrders = new ArrayList<>();
// Get diners amount from previous activity
Intent intent = getIntent();
mDinersAmount = intent.getIntExtra(Constants.KEY_DINNERS_AMOUNT, 1);
// Initialise PageHeader Recycler
mHeaderAdapter = new PageHeaderAdapter(this, mDinersAmount, this);
final RecyclerView recyclerPageHeader = (RecyclerView) findViewById(R.id.recyclerViewPagerHeader);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerPageHeader.setLayoutManager(linearLayoutManager);
recyclerPageHeader.setAdapter(mHeaderAdapter);
// Initialise ViewPager
mViewPagerDiners = (ViewPager) findViewById(R.id.viewPagerDiners);
FragmentManager fragmentManager = getSupportFragmentManager();
mDinersPagerAdapter = new DinersPagerAdapter(fragmentManager, mDinersAmount);
mViewPagerDiners.setAdapter(mDinersPagerAdapter);
// ViewPager Listener - synchronise with headers recycler
mViewPagerDiners.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
// Gets position for selected page
#Override
public void onPageSelected(int position) {
mHeaderAdapter.selectItem(position);
linearLayoutManager.smoothScrollToPosition(recyclerPageHeader, null,position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
// HeaderPage Adapter Callbacks
// Scroll ViewPager by clicked Header
#Override
public void onItemClick(int position) {
mViewPagerDiners.setCurrentItem(position, true);
}
// DinerFragment.OrderDialog.Callbacks
// Send data to PagerAdapter that would sent to each fragment
#Override
public void onDialogAddClick(Order order) {
Log.d("test", "onDialogAddClick");
mOrders.add(order);
mDinersPagerAdapter.updateOrders();
}
}
PagerAdapter
package com.slavafleer.tipcalculator02;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.ArrayList;
/**
* PagerAdapter for ManualModeActivity ViewPager
*/
public class DinersPagerAdapter extends FragmentPagerAdapter {
private int mDinersAmount;
private ArrayList<DinerFragment> mDinerFragments;
public DinersPagerAdapter(FragmentManager fm, int dinersAmount) {
super(fm);
mDinersAmount = dinersAmount;
mDinerFragments = new ArrayList<>();
}
#Override
public Fragment getItem(int position) {
// Insert diners amount to fragment
Bundle bundle = new Bundle();
bundle.putInt(Constants.KEY_DINNERS_AMOUNT, mDinersAmount);
bundle.putInt(Constants.KEY_CURRENT_PAGE, position);
DinerFragment dinerFragment = new DinerFragment();
dinerFragment.setArguments(bundle);
mDinerFragments.add(dinerFragment); // save fragments references
return dinerFragment;
}
// Diners amount + All
#Override
public int getCount() {
return mDinersAmount + 1;
}
// Update order list in each fragment of view pager
public void updateOrders() {
for(DinerFragment dinerFragment : mDinerFragments) {
dinerFragment.onResume();
}
}
}
Fragment
package com.slavafleer.tipcalculator02;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.slavafleer.tipcalculator02.recycler.OrdersAdapter;
import java.util.ArrayList;
/**
* Diner Fragment Class
*/
public class DinerFragment extends Fragment implements OrderDialog.Callbacks {
private ArrayList<Order> mOrders = new ArrayList<>();
private RecyclerView mRecyclerViewOrders;
private ImageView mImageViewAddOrderButton;
private int mDinersAmount;
private OrdersAdapter mOrdersAdapter;
private int mDinerId;
private Callbacks mCallbacks;
public DinerFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("test", "onCreateView");
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_diner, container, false);
mCallbacks = (Callbacks) inflater.getContext();
// Get Diners Amount
final Bundle bundle = getArguments();
if(bundle != null) {
mDinersAmount = bundle.getInt(Constants.KEY_DINNERS_AMOUNT);
mDinerId = bundle.getInt(Constants.KEY_CURRENT_PAGE);
Log.d("test", "onCreateView " + mDinerId);
}
mRecyclerViewOrders = (RecyclerView) view.findViewById(R.id.recyclerViewOrders);
mOrdersAdapter = new OrdersAdapter(getActivity(), mOrders);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerViewOrders.setLayoutManager(linearLayoutManager);
mRecyclerViewOrders.setAdapter(mOrdersAdapter);
// Due to the bug, we could use just listener and not OnClick in Fragment
mImageViewAddOrderButton = (ImageView) view.findViewById(R.id.imageViewAddButton);
mImageViewAddOrderButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ArrayList<Integer> currentPage = new ArrayList<>();
currentPage.add(mDinerId);
OrderDialog orderDialog = new OrderDialog(getActivity(),
mDinersAmount, currentPage, DinerFragment.this);
orderDialog.show();
}
});
return view;
}
#Override
public void onResume() {
super.onResume();
Log.d("test", "onResume " + mDinerId);
ManualModeActivity activity = (ManualModeActivity) getActivity();
mOrders = activity.getOrders();
for(Order order : mOrders) {
Log.d("test", order.getPrice() + "");
}
int size = mOrders.size();
mOrdersAdapter.notifyDataSetChanged();
mRecyclerViewOrders.smoothScrollToPosition(size);
}
// Blank OrderDialog.Callbacks
// used due to Implements for creation OrderDialog
#Override
public void onDialogAddClick(Order order) {
mCallbacks.onDialogAddClick(order);
}
public interface Callbacks {
void onDialogAddClick(Order order);
}
}
Instead of using onResume use the onPageSelected method and used the passed fragment for context to call the updating method in the fragment.
Finally what I did is replacing mOrdersAdapter.notifyDataSetChanged() on recreating the adapter. I understand that is not a very smart solution but visually it does work as I needed.
I would not mark it as answer cause I still want to know why it acts like I wrote before.
Thanks again.
// mOrdersAdapter.notifyDataSetChanged();
mOrdersAdapter = new OrdersAdapter(getActivity(), mOrders);
mRecyclerViewOrders.setAdapter(mOrdersAdapter);
ViewPager adapter creates 2 fragments at the same time. for instance when you're on page 0, it also creates page 1(lifecycle for page 1: OnCreate->OnCreateView->OnResume->OnPause->OnResume).When you swipe to page 1 only method that is being called is SetMenuVisibility. So in order to update data for page 1 is to call setMenuVisibilty inside of Fragment:
#Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if(menuVisible && isResumed()){
settingAdapter();
}
}
So here inside of settingAdapter i reloaded data.
so far,it's the best trick i made toward fragments with recyclerviews inside viewpager. But still there are few milliseconds delay for populating fragment with new data)))
I hope this will help you

Transfering class from an activity to fragment

Im trying to use viewPager so I want to change my class from an activity to fragment, but Im getting alot of errors, so can you tell me whats wrong and what I need to do?
Here is my original activity :
package com.pickapp.pachu.pickapp;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.content.Intent;
import java.util.Random;
public class MainScreen extends Activity implements OnClickListener {
private TitlesDB titles;
private Button getPickUpLine;
private TextView pickUpLine;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
titles = new TitlesDB(this);
initDB();
initialize();
}
public void initialize() {
this.getPickUpLine = (Button) findViewById(R.id.bGetLine);
this.getPickUpLine.setOnClickListener(this);
this.pickUpLine = (TextView) findViewById(R.id.tvLine);
this.pickUpLine.setOnClickListener(this);
}
public void initDB() {
titles.open();
if (!this.titles.isExist()) {
titles.createEntry("The I \n Have Cancer");
titles.createEntry("The Ocean");
}
titles.close();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bGetLine:
titles.open();
Random rnd = new Random();
int index = rnd.nextInt(titles.getLength()) + 1;
pickUpLine.setText(titles.getTitleById(index));
titles.close();
break;
case R.id.tvLine:
if(!pickUpLine.getText().toString().equals(""))
{
Intent intent = new Intent(this, PickAppLine.class);
intent.putExtra("key", pickUpLine.getText().toString());
startActivity(intent);
}
break;
}
}
}
Here is what I tried :
package com.pickapp.pachu.pickapp;
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.Button;
import android.widget.TextView;
/**
* Created by Golan on 19/08/2014.
*/
public class MainScreenFragment extends Fragment implements OnClickListener{
private TitlesDB titles;
private Button getPickUpLine;
private TextView pickUpLine;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
titles = new TitlesDB(getActivity());
initDB();
View v = getView();
initialize(v);
return inflater.inflate(R.layout.activity_main_screen, container, false);
}
public void initialize(View v) {
this.getPickUpLine = (Button) v.findViewById(R.id.bGetLine);
this.getPickUpLine.setOnClickListener(this);
this.pickUpLine = (TextView) v.findViewById(R.id.tvLine);
this.pickUpLine.setOnClickListener(this);
}
public void initDB() {
titles.open();
if (!this.titles.isExist()) {
titles.createEntry("The I \n Have Cancer");
titles.createEntry("The Ocean");
}
titles.close();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bGetLine:
titles.open();
Random rnd = new Random();
int index = rnd.nextInt(titles.getLength()) + 1;
pickUpLine.setText(titles.getTitleById(index));
titles.close();
break;
case R.id.tvLine:
if(!pickUpLine.getText().toString().equals(""))
{
Intent intent = new Intent(this, PickAppLine.class);
intent.putExtra("key", pickUpLine.getText().toString());
startActivity(intent);
}
break;
}
}
}
We won't just fix all your code. You have to do that yourself! Remove everything that you don't need at the beginning and start adding one after the other again. Fix all the errors on the way. It is hard to know what the actual problem is when everything is wrong.
One thing that I see right away that definitely does not work is this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_main_screen, container, false); // NO, NO, NO!!
titles = new TitlesDB(getActivity());
initDB();
initialize();
}
You have a return statement in the method BEFORE you have more code. That can not work. The return statement has to be at the end!

change the items in a ListView from another fragment

I have two fragments, lets call them Fragment A and Fragment B, which are a part of a NavigationDrawer (this is the activity they a bound to). In Fragment A I have a button. When this button is pressed, I would like another item added to the ListView in Fragment B.
What is the best way to do this? Use Intents, SavedPreferences, making something public(?) or something else?
EDIT 5: 20/7/13 This is with srains latest code
This is the NavigationDrawer that I use to start the fragments:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class Navigation_Drawer extends FragmentActivity {
public DrawerLayout mDrawerLayout; // Creates a DrawerLayout called_.
public ListView mDrawerList;
public ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mNoterActivities; // This creates a string array called _.
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
// Just setting up the navigation drawer
} // End of onCreate
// Removed the menu
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
selectItem(position);
}
}
private void selectItem(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
if (position == 0) {
Fragment qnfragment = new QuickNoteFragment();
((FragmentBase) qnfragment).setContext(this);
Bundle args = new Bundle(); // Creates a bundle called args
args.putInt(QuickNoteFragment.ARG_nOTERACTIVITY_NUMBER, position);
qnfragment.setArguments(args);
fragmentManager.beginTransaction()
.replace(R.id.content_frame, qnfragment).commit();
} else if (position == 3) {
Fragment pendViewPager = new PendViewPager(); // This is a ViewPager that includes HistoryFragment
((FragmentBase) pendViewPager).setContext(this);
Bundle args = new Bundle();
pendViewPager.setArguments(args);
fragmentManager.beginTransaction()
.replace(R.id.content_frame, pendViewPager).commit();
}
// Update title etc
}
#Override
protected void onPostCreate(Bundle savedInstanceState) { // Used for the NavDrawer toggle
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) { // Used for the NavDrawer toggle
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
This is QuickNoteFragment:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class QuickNoteFragment extends FragmentBase implements OnClickListener {
public static final String ARG_nOTERACTIVITY_NUMBER = "noter_activity";
Button b_create;
// removed other defining stuff
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.quicknote, container, false);
int i = getArguments().getInt(ARG_nOTERACTIVITY_NUMBER);
String noter_activity = getResources().getStringArray(
R.array.noter_array)[i];
FragmentManager fm = getFragmentManager();
setRetainInstance(true);
b_create = (Button) rootView.findViewById(R.id.qn_b_create);
// Removed other stuff
getActivity().setTitle(noter_activity);
return rootView;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.qn_b_create:
String data = "String data";
DataModel.getInstance().addItem(data);
break;
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
}
}
public interface OnItemAddedHandler { // Srains code
public void onItemAdded(Object data);
}
}
This is HistoryFragment (Remember it is part of a ViewPager):
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.RiThBo.noter.QuickNoteFragment.OnItemAddedHandler;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class HistoryFragment extends FragmentBase implements OnItemAddedHandler {
ListView lv;
List<Map<String, String>> planetsList = new ArrayList<Map<String, String>>();
SimpleAdapter simpleAdpt;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.history, container, false);
initList();
ListView lv = (ListView) view.findViewById(R.id.listView);
simpleAdpt = new SimpleAdapter(getActivity(), planetsList,
android.R.layout.simple_list_item_1, new String[] { "planet" },
new int[] { android.R.id.text1 });
lv.setAdapter(simpleAdpt);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parentAdapter, View view,
int position, long id) {
// We know the View is a TextView so we can cast it
TextView clickedView = (TextView) view;
Toast.makeText(
getActivity(),
"Item with id [" + id + "] - Position [" + position
+ "] - Planet [" + clickedView.getText() + "]",
Toast.LENGTH_SHORT).show();
}
});
registerForContextMenu(lv);
return view;
}
private void initList() {
// We populate the planets
planetsList.add(createPlanet("planet", "Mercury"));
planetsList.add(createPlanet("planet", "Venus"));
planetsList.add(createPlanet("planet", "Mars"));
planetsList.add(createPlanet("planet", "Jupiter"));
planetsList.add(createPlanet("planet", "Saturn"));
planetsList.add(createPlanet("planet", "Uranus"));
planetsList.add(createPlanet("planet", "Neptune"));
}
private HashMap<String, String> createPlanet(String key, String name) {
HashMap<String, String> planet = new HashMap<String, String>();
planet.put(key, name);
return planet;
}
// We want to create a context Menu when the user long click on an item
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterContextMenuInfo aInfo = (AdapterContextMenuInfo) menuInfo;
// We know that each row in the adapter is a Map
HashMap map = (HashMap) simpleAdpt.getItem(aInfo.position);
menu.setHeaderTitle("Options for " + map.get("planet"));
menu.add(1, 1, 1, "Details");
menu.add(1, 2, 2, "Delete");
}
#Override
public void onItemAdded(Object data) {
// to add item
String string = String.valueOf(data);
Toast.makeText(getContext(), "Data: " + string, Toast.LENGTH_SHORT).show();
planetsList.add(createPlanet("planet", string));
}
#Override
public void onStart() {
super.onStart();
DataModel.getInstance().setOnItemAddedHandler(this);
}
}
This is FragmentBase:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
public class FragmentBase extends Fragment {
private FragmentActivity mActivity; // I changed it to FragmentActivity because Activity was not working, and my `NavDrawer` is a FragmentActivity.
public void setContext(FragmentActivity activity) {
mActivity = mActivity;
}
public FragmentActivity getContext() {
return mActivity;
}
}
This is DataModel:
import android.util.Log;
import com.xxx.xxx.QuickNoteFragment.OnItemAddedHandler;
public class DataModel {
private static DataModel instance;
private static OnItemAddedHandler mOnItemAddHandler;
public static DataModel getInstance() {
if (null == instance) {
instance = new DataModel();
}
return instance;
}
public void setOnItemAddedHandler(OnItemAddedHandler handler) {
mOnItemAddHandler = handler;
}
public void addItem(Object data) {
if (null != mOnItemAddHandler)
mOnItemAddHandler.onItemAdded(data);
else {
Log.i("is context null?", "yes!");
}
}
}
Thank you
I suggest you to use interface and MVC, that will make your code much more maintainable.
First you need an interface:
public interface OnItemAddedHandler {
public void onItemAdded(Object data);
}
Then, you will need a data model:
public class DataModel {
private static DataModel instance;
private static OnItemAddedHandler mOnItemAddHandler;
public static DataModel getInstance() {
if (null == instance) {
instance = new DataModel();
}
return instance;
}
public void setOnItemAddedHandler(OnItemAddedHandler handler) {
mOnItemAddHandler = handler;
}
public void addItem(Object data) {
if (null != mOnItemAddHandler)
mOnItemAddHandler.onItemAdded(data);
}
}
When you click the button, you can add data into the datamodel:
Object data = null;
DataModel.getInstance().addItem(data);
Then, the FragmentB implements the interface OnItemAddedHandler to add item
public class FragmentB implements OnItemAddedHandler {
#Override
public void onItemAdded(Object data) {
// to add item
}
}
also, When the FragmentB start, you should register itself to DataModel:
public class FragmentB implements OnItemAddedHandler {
#Override
public void onItemAdded(Object data) {
// to add item
}
#Override
protected void onStart() {
super.onStart();
DataModel.getInstance().setOnItemAddedHandler(this);
}
}
You also can add DataModel.getInstance().setOnItemAddedHandler(this); to the onCreate method of FragmentB
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DataModel.getInstance().setOnItemAddedHandler(this);
// do other things
}
update
you can send string simply:
String data = "some string";
DataModel.getInstance().addItem(data);
then on FragementB
public class FragmentB implements OnItemAddedHandler {
#Override
public void onItemAdded(Object data) {
// get what you send into method DataModel.getInstance().addItem(data);
String string = String.valueOf(data);
}
}
update
OK. You have add DataModel.getInstance().setOnItemAddedHandler(this) in onCreateView method, so there is no need to add it in onStart() method. You can remove the whole onStart method.
onStart will be called on the fragment start, we do not need to call it in onCreateView. And on onItemAdded will be call when call the method DataModel.getInstance().addItem(data), we do not need to call it in onCreateView neither.
so, you can remove the code below from onCreateView method:
DataModel.getInstance().setOnItemAddedHandler(this);
// remove the methods below
// onItemAdded(getView());
// onStart();
You have another fragment where there is a button, you can add the codes below in the clickhandler function:
String data = "some string";
DataModel.getInstance().addItem(data);
update3
I think the HistoryFragment has been detached after you when to QuickNoteFragment
You can add code to HistoryFragment to check:
#Override
public void onDetach() {
super.onDetach();
Log.i("test", String.format("onDetach! %s", getActivity() == null));
}
update4
I think HistoryFragment and QuickNoteFragment should has an parent class, named FragmentBase:
public class FragmentBase extends Fragment {
private Activity mActivity;
public void setContext(Activity activity) {
mActivity = mActivity;
}
public Activity getContext() {
return mActivity;
}
}
HistoryFragment and QuickNoteFragment extends FragmentBase. Then when you switch between them, you can call setContext to set a Activity, like:
private void selectItem(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
if (position == 0) {
Fragment qnfragment = new QuickNoteFragment();
qnfragment.setContext(this);
// ...
} else if (position == 1) {
Fragment pagerFragment = new RemViewPager();
pagerFragment.setContext(this);
// ...
}
}
now, we can get a non-null activity in HistoryFragment by calling getContext, so we can change onItemAdded method to:
#Override
public void onItemAdded(Object data) {
// to add item
String string = String.valueOf(data);
Toast.makeText(getContext(), "Data: " + string, Toast.LENGTH_SHORT).show();
planetsList.add(createPlanet("planet", string));
}
I hope this would work.
Some good design principals:
An activity can know everything pubic about any Fragment it contains.
A Fragment should not know anything about the specific Activities that contain it.
A Fragment should NEVER know about other fragments that may or may not be contained in the Parent activity.
A suggested approach (informal design pattern) based on these principles.
Each fragment should declare an interface to be implemented by its parent activity:
public class MyFragment extends Fragment
{
public interface Parent
{
void onMyFragmentSomeAction();
}
private Parent mParent;
public onAttach(Activity activity)
{
mParent = (Parent) activity;
}
// This would actually be in a listener. Simplifying to save typing.
void onSomeButtonClick(View button)
{
mParent.onMyFragmentSomeAction();
}
}
And the activity should implement the appropriate interfaces for all of its contained fragments.
public class MyActivity extends Activity
implements MyFragment.Parent,
YourFragment.Parent,
HisFragment.Parent
{
[usual Activity code]
void onMyFragmentSomeAction()
{
if yourFragment is showing
{
yourFragment.reactToSomeAction();
}
if hisFragment is showing
{
hisFragment.observeThatSomeActionHappened();
}
[etc]
}
The broadcast approach is good, too, but it's pretty heavyweight and it requires the target Fragment to know what broadcasts will be sent by the source Fragment.
Use Broadcast. Send a boradcast from A, and B will receive and handle it.
Add a public method to B, for example, public void addListItem(), which will add data to listview in B. Fragment A try to find the instance of Fragment B using FragmentMananger.findFragmentByTag() and invoke this method.

Categories

Resources