I'm trying to call fragment function from dialogfragment. My application is based on navigation drawer which contains container for fragments. At one of my fragments I make retrofit request and I also can open dialogfragment from this fragment. But I faced with one very serious problem - I can't get SharedPreferences after calling fragment function from dialogFragment. Here how I call this method:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
JobList jobList = new JobList();
jobList.testFunction();
}
});
and here is my testFunction():
public void testFunction() {
sp = Objects.requireNonNull(getActivity()).getSharedPreferences("app_data", 0);
Log.w("MY_tag", sp.getString("access_token", ""));
}
my testFunction contains only experimental logs, because I try to get data from sharedpreferences but I get only error:
java.lang.NullPointerException
after putting breakpoint I understood that I can't receive any context for getting sharedPreferences. I can't understand how to solve my problem, and I will be happy if smb help me with the solution.
please try as follows
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
JobList jobList = new JobList();
jobList.testFunction(view);
}
});
public void testFunction(View view) {
sp = Objects.requireNonNull(view.getContext()).getSharedPreferences("app_data", 0);
Log.w("MY_tag", sp.getString("access_token", ""));
}
Easy and Recommended way:
First make a callback in fragment: How?
interface DialogCallBack{
void callback(View view);
}
implement interface on your fragment, and when you create constructor for your dialogfragment, just pass the callback for that fragment.
Then in your dialogFragment:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
listener.callback(view);
}
});
listener call interface method which is implemented on fragment. So do this inside your fragment:
#override
callback(View view){
testFunction(view);
}
Related
I have an Recycler.Adapter and my onBindViewHolder is like this:
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final String url = urls.get(position);
final width_height wh = whs.get(position);
holder.imageView.setClickable(true);
Picasso.with(context)
.load(url).resize(wh.width, wh.height).centerCrop()
.into(holder.imageView);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialogFragment.show(fragmentManager, "");
dialogFragment.setImage(url);
dialogFragment.setRating(0);
}
});
holder.textView.setText(position + "");
holder.textView.setClickable(true);
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialogFragment.show(fragmentManager, "");
dialogFragment.setImage(url);
dialogFragment.setRating(0);
}
});
}
The dialogFragment is already instantiated in the contructor of Adapter. However, its onCreateView has not been called yet when the holder is clicked. And the setImage and setRating need to modify its imageView and RatingBar, which are null unless the onCreateView of the fragment is called. Is there a way to resolve this?
That's because DialogFragment.show commits asynchronously. In your case you'd want it to use DialogFragment.showNow instead so it commits synchronously.
#Override
public void onClick(View v) {
dialogFragment.showNow(fragmentManager, "");
dialogFragment.setImage(url);
dialogFragment.setRating(0);
}
Otherwise I'd suggest to create new DialogFragment every time the button is clicked, and pass image url and rating as arguments before it is shown.
A more correct way would be to have the setImage method and setRating method check for null. If null, they should save the value to variable, and onCreate should use those values to set.
For example (not tested);
void setImage(src) {
if (mImage == null)
mImageSource = src;
else
mImage.setImage(src);
}
void onCreateView(...) {
...
if (mImageSource != null)
mImage.setImage(mImageSource);
mImageSource = null;
}
This way you can correctly use the asynchronous dialog calls.
Here there is minor issue Like I had Recyclerview in dialog fragment.ie name of bank in recyclerview When we select one bank in recyclerview and after dialogfragment dismiss that name should be appear on Button ie when we selected Union Bank from dialog fragment it should appear on button.Issue is when we click on button then its text changes rather then on time of dismiss listener
here is Dialog dismissal code:
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getContext(), mRecyclerView, new ClickListener() {
#Override
public void onClick(View view, final int position) {
Employee e = bank.get(position);
Toast.makeText(getContext(), e.getBank_id() + "" + e.getBank_name(), Toast.LENGTH_SHORT).show();
getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
Employee e = bank.get(position);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor edit = sp.edit();
edit.putString("bankname", e.getBank_name());
edit.commit();
}
});
c.onItemSelect(e.getBank_name());
onDismiss(getDialog());
}
Here is onclick event where dialog opens and where the value should be printed:
select_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fm=getFragmentManager();
DialogRecyclerview dr = new DialogRecyclerview(AccountManagement_banks.this,callback);
dr.setRetainInstance(true);
dr.show(getSupportFragmentManager(), "Dialog");
SharedPreferences st = PreferenceManager.getDefaultSharedPreferences(AccountManagement_banks.this);
String mode=st.getString("bankname","");
select_button.setText(mode);
Toast.makeText(getApplication(),mode,Toast.LENGTH_SHORT).show();
}
});
Same in:
#Override
public void onItemSelect(String text) {
select_button.setText(text);
}
Here I had created new Interface:
public interface CallBack {
void onItemSelect(String text);}
just create a callback and implement it on your main class (where you want to display the name) and pass the callback instance to adapter. Now dialog fragment, now when you are selecting any item just call callback function which is overridden in main calss and inside this function just change the text of your button.
public interface CallBack {
void onItemSelect(String text);
}
implement this in your main class like
public class MainActivity extends Activity implements CallBack {
.
.
.
public void onItemSelect(String text){
button.setText(text);
}
.
.
}
when you are opening your dialogfragment from your main activity just pass MainActivity.this as an argument in the dialog constructor. And in your Dialog class constructor write your code like this
private Callback callback;
public YourDialog(Context context, Callback callback){
this.callback = callback;
}
and when you selecting list item just call
callback.onItemSelect(e.getBank_name());
Hope it will help you out.
I saw some different ways of implementing onItemClickListener for RecyclerView. My favourite is to use interface callback:
Interface:
public interface OnClickListener {
void onCardClick(View v);
void onFavouriteButtonClick(View v);
void onRemoveClick(View v);
//Other clickable areas
}
In adapter:
currentView.favouriteButton.setTag(currentItem.getId());
currentView.favouriteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (OnClickListener != null){
OnClickListener.onFavouriteButtonClick(v);
}
}
});
In main activity/fragment
adapter = new CardAdapter( .... new OnClickListener() {
#Override
public void onFavouriteButtonClick(View v) {
int id = Integer.parse(v.getTag().toString());
//Do your stuff
}
....
});
So, I have some questions:
is it good way of handling things?
will performance be slow if number of items will grow?
any reasons why I shouldn't use this approach?
I think you could improve upon this by not passing the view outside of the adapter.
// Create an object that encapulates the information for each card
public class CardInfo {
// Whatever you want to show in your card
}
// Create a listener for items instead of views
public interface OnCardAction {
void onCardSelected(CardInfo cardInfo);
void onFavoriteSelected(CardInfo cardInfo);
void onCardRemoved(CardInfo cardInfo);
}
// In your adapter
favoriteButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// You many need to check if onCardActionLisetner is null
CardInfo cardInfo = getItemAt(viewHolder.getAdapterPosition());
onCardActionListener.onFavoriteSelected(cardInfo);
}
});
NOTE: If you are passing the listener in the constructor can either make it required (throw error if it is null) or not even create View.OnClickListner to reduce the number of null checks.
Is it wrong to do that or will it work just fine? I'm trying to make every relative layout clickable and when you click on it it takes you to a new page where the mGameTitle and mReleaseDate are passed to this new activity.
I'm doubting if it will work 'cause I'm getting an error with View.OnClickListener; must either be declared abstract or implement abstract method 'onClick(View)' in 'OnClickListener
public void onBindViewHolder(final ViewHolderUpcoming viewHolderUpcoming, int i) {
Game currentGame = listOfGames.get(i);
viewHolderUpcoming.mReleaseDate.setText(currentGame.getReleaseDate());
viewHolderUpcoming.mGameTitle.setText(currentGame.getTitle());
viewHolderUpcoming.mLayout.setOnClickListener(new View.OnClickListener() {
//Intent intent = new Intent(this, GamePage.class);
});
}
As the error states, you need to implement onClick(View).
viewHolderUpcoming.mLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
//TODO: Implementation
}
});
I know there are similar questions asked before in SO, but sorry to say that, none of them are serving my purpose.
I have a button in an activity class, and I want to give its functionality in another class.
Below is my HomeActivity code:
// Tile Button
tileButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TileButton tileView = new TileButton();
tileView.tile();
}
});
And here is TileButton.java class code:
public class TileButton {
HomeActivity homeActivity = new HomeActivity();
View view = homeActivity.hometabView;
public void tile(){
if(view.isShown()){
view.setVisibility(View.INVISIBLE);
}else{
view.setVisibility(View.VISIBLE);
}
}
}
Now when I press the tile button, a Null Pointer Exception is thrown. Below is the LogCat entry.
10-04 10:32:07.833: E/AndroidRuntime(5330): java.lang.NullPointerException
How do I solve this problem? Please help
Change:
public class TileButton {
public void tile(View view){
if(view.isShown()){
view.setVisibility(View.INVISIBLE);
}else{
view.setVisibility(View.VISIBLE);
}
}
}
// Tile Button
tileButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TileButton tileView = new TileButton();
tileView.tile(v);// you can pass any view from here
}
});
If you want to have same operation in both the activities, Create a public method in one of the activity and just call the method onClick of both buttons. But you cannot control the visibility of an activity which is not even on screen.