I'm trying to create a function that once a user clicks on the recycler view, a dialog box will pop out but I am stuck on the error as mentioned below. When I try to initialize AlertDialog.build and put this as the parameter, it shows an error. I had tried with a few other parameters like context, getActivity. But the error is still the same.
The code below is my full code
package com.example.tuitioncentre;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Observable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.firestore.DocumentSnapshot;
public class myadapter_tutorlist extends FirebaseRecyclerAdapter<User,myadapter_tutorlist.myviewholder> {
AlertDialog.Builder builder;
public myadapter_tutorlist(#NonNull FirebaseRecyclerOptions<User> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull final myviewholder holder, int position, #NonNull final User model) {
holder.name.setText("Tutor's Name:" + model.getUsername());
holder.phone.setText("Phone No:" + model.getPhone());
holder.email.setText("Email:" + model.getEmail());
holder.status.setText("Status: " + model.getActive().toString());
builder = new AlertDialog.Builder(this);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
//Toast.makeText(v.getContext(),model.getUsername(),Toast.LENGTH_SHORT).show();
builder.setMessage(R.string.dialog_message) .setTitle(R.string.dialog_title);
builder.setMessage("Do you want to activate tutor account ?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Toast.makeText(v.getContext(),"you choose yes action for alertbox", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Action for 'NO' Button
dialog.cancel();
Toast.makeText(v.getContext(),"you choose no action for alertbox", Toast.LENGTH_SHORT).show();
}
});
//Creating dialog box
AlertDialog alert = builder.create();
//Setting the title manually
alert.setTitle("AlertDialogExample");
alert.show();
}
});
}
#NonNull
#Override
public myviewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//put singlerow xml into view holder
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.singlerow,parent,false);
return new myviewholder(view);
}
class myviewholder extends RecyclerView.ViewHolder{
TextView name,phone,email,status;
public myviewholder(#NonNull View itemView) {
super(itemView);
name=(TextView)itemView.findViewById(R.id.nametext);
phone=(TextView)itemView.findViewById(R.id.phonetext);
email=(TextView)itemView.findViewById(R.id.emailtext);
status=(TextView)itemView.findViewById(R.id.statustext);
}
}
}
Passing "this" to AlertDialog.Builder(this); won't work as you're trying to pass a reference of your Adapter.
There are two correct ways to achieve this:
Add a variable to reference your Activity like Activity mActivity; in your Adapter class. Then, in your Activity class where you're initializing the Adapter, you can pass your activity context as "this". You can achieve it either with a constructor in the Adapter class or in your Activity class use your adapter instance once it is initialized to access the mActivity variable and set it.
Alternatively, you can use a view interface and implement it in your activity, override the method to show the AlertDialog in your activity. Then add a reference variable of that interface in your Adapter like SomeInterface mInfterface; and initialize it in your Activity class the same way mentioned above. Then you can just call that method to show the AlertDialog and pass the data to that method from the Adapter to show all information like -
mInterface.showAlertDialog(model);
first create this class:
class RecyclerItemClickListener extends RecyclerView.SimpleOnItemTouchListener {
interface OnRecyclerClickListener{
void onItemClick(View view, int position);
}
private final OnRecyclerClickListener mListener;
private final GestureDetectorCompat mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView,
OnRecyclerClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapUp(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null){
Log.d(TAG, "onSingleTapUp: calling listener.onItemClick");
mListener.onItemClick(childView, recyclerView.getChildAdapterPosition(childView));
}
return true;
}
});
}
#Override
public boolean onInterceptTouchEvent(#NonNull RecyclerView rv, #NonNull MotionEvent e) {
if (mGestureDetector != null){
boolean result = mGestureDetector.onTouchEvent(e);
return result;
} else {
return false;
}
}
}
and in MainActivity:
in onCreate method: first define recyclerView variable by findviewbyid() then:
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, recyclerView, this));
then implement onItemClick() method. you can define alert dialog here:
#Override
public void onItemClick(View view, int position) {
Toast.makeText(this, "normal tap on position " + position, Toast.LENGTH_SHORT).show();
}
First pass the context from the Activity or Fragment:
For activity:
myadapter_tutorlist(options, this);
For Fragment:
myadapter_tutorlist(options, getActivity());
Then create a Context variable in side the Adapter class:
public class myadapter_tutorlist extends FirebaseRecyclerAdapter<User,myadapter_tutorlist.myviewholder> {
AlertDialog.Builder builder;
Context context;
public myadapter_tutorlist(#NonNull FirebaseRecyclerOptions<User> options) {
super(options);
this.context = context;
}
Now you can pass this context to your AlertDialog
builder = new AlertDialog.Builder(context);
Related
I have an issue deleting item from app. It,s Actually a notes app in which i have created a AlertDialog function that deletes notes. here is code for my function
private void showDeleteDialog(int position) {
AlertDialog.Builder alert = new AlertDialog.Builder(context)
.setTitle("Delete view")
.setMessage("Are you sure to delete")
.setIcon(R.drawable.ic_baseline_delete_24)
.setPositiveButton("yes", (dialogInterface, i) -> databaseHelper.notesDao().deleteNotes(new Notes(arrNotes.get(position).id, arrNotes.get(position).title, arrNotes.get(position).text)))
.setNegativeButton("No", (dialogInterface, i) -> {
});
alert.show();
}
Here i call it
holder.llView.setOnLongClickListener(view -> {
showDeleteDialog(position);
return true;
});
When i click yes then app crashed but it succuessfully delets notes from database.This is the error i got
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{a4d7d56 position=1 id=-1, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached no parent} androidx.recyclerview.widget.RecyclerView{815f028 VFED..... ......I. 31,171-689,776 #7f090165 app:id/recycler_view}, adapter:com.example.keepnotes.RecyclerViewAdapter#773a141, layout:androidx.recyclerview.widget.StaggeredGridLayoutManager#a3a6e6, context:com.example.keepnotes.MainActivity#3065e55
All of this is in RecyclerView Adapter. The code for recyclerView adapter is following
package com.example.keepnotes;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
Context context;
ArrayList<Notes> arrNotes;
DatabaseHelper databaseHelper;
private RecyclerView.RecyclerListener listener;
RecyclerViewAdapter(Context context, ArrayList<Notes> arrNotes, DatabaseHelper databaseHelper) {
this.context = context;
this.arrNotes = arrNotes;
this.databaseHelper = databaseHelper;
}
public RecyclerViewAdapter(ArrayList<Notes> arrNotes, RecyclerView.RecyclerListener listener) {
this.arrNotes = arrNotes;
this.listener = listener;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.single_view, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, #SuppressLint("RecyclerView") int position) {
holder.title.setText(arrNotes.get(position).title);
holder.body.setText(arrNotes.get(position).text);
holder.index.setText(String.valueOf(position + 1));
holder.llView.setOnClickListener(view -> {
Intent iNext = new Intent(context, ViewActivity.class);
iNext.putExtra("title", arrNotes.get(position).title);
iNext.putExtra("text", arrNotes.get(position).text);
context.startActivity(iNext);
});
holder.llView.setOnLongClickListener(view -> {
showDeleteDialog(position);
return true;
});
}
#Override
public int getItemCount() {
return arrNotes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView title, body, index;
CardView llView;
public ViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.text_title_view);
body = itemView.findViewById(R.id.text_text_view);
index = itemView.findViewById(R.id.index);
llView = itemView.findViewById(R.id.card_View);
databaseHelper = DatabaseHelper.getDatabase(context);
}
}
private void showDeleteDialog(int position) {
AlertDialog.Builder alert = new AlertDialog.Builder(context)
.setTitle("Delete view")
.setMessage("Are you sure to delete")
.setIcon(R.drawable.ic_baseline_delete_24)
.setPositiveButton("yes", (dialogInterface, i) -> databaseHelper.notesDao().deleteNotes(new Notes(arrNotes.get(position).id, arrNotes.get(position).title, arrNotes.get(position).text)))
.setNegativeButton("No", (dialogInterface, i) -> {
});
alert.show();
}
}
How can i get rid of this error????
It is Solved, Actually, in Live Data, I was using notifyiteminserted, I changed that to notifyDataSetChnaged.
I have one big problem ( for me )
I have some items from api in RecycleViewHolder.class in that class i tell where is xml file of that items.. Now my problem is because i have preference settings in mainactivity and when i define background color to black of whole app my text will be in the same color "black" and i can not see anything in app because of colour. Now i need your help how to change colour of textview in mainactivity,when i try to make findviewbyid in MainActivity and call method setTextColor I get nullpointexception because it is already connected to xml in RecycleViewHolder Class.
This is RecyclceViewHolder class that contains textview of price that i wanna to change colour from mainactivity.
package com.example.domo.cryptotrace;
import android.support.v7.widget.RecyclerView;
import android.widget.TextView;
import android.view.View;
/**
* Created by Antun on 31.1.2018..
*/
public class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView name, symbol, rank, percentChange1h, percentChange24h, percentChange7d;
public TextView price;
public RecyclerViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
name = itemView.findViewById(R.id.name);
symbol= itemView.findViewById(R.id.symbol);
rank = itemView.findViewById(R.id.
rank);
price=itemView.findViewById(R.id.price);
percentChange1h=itemView.findViewById(R.id.percent_change_1h);
percentChange24h=itemView.findViewById(R.id.percent_change_24h);
percentChange7d=itemView.findViewById(R.id.percent_change_7d);
}
#Override
public void onClick(View view) {
}
}
This is mainactivity (in this class i wanna change
RecyclerViewHolder --> itemView--> price color)
package com.example.domo.cryptotrace;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.View;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Button;
import com.crashlytics.android.Crashlytics;
import java.util.List;
import io.fabric.sdk.android.Fabric;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
public Button register;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fabric.with(this, new Crashlytics());
final Fabric fabric = new Fabric.Builder(this)
.kits(new Crashlytics())
.debuggable(true)
.build();
Fabric.with(fabric);
setContentView(R.layout.activity_main);
getUserList();
register=findViewById(R.id.register);
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, LoginSys.class);
startActivity(intent);
}
});
}
#Override
protected void onResume() {
super.onResume();
getPreference();
}
//Ovo je klasa koju smo sami gore kreirali kako bi mogli odrediti boje od pozadine kroz Settings
//Tu još možeš i mjenjati text boju od texViewa sa metodom ||myTextView.setTextColor(0xAARRGGBB);||
//Ili ovako ||ContextCompat.getColor(context, R.color.your_color);||
private void getPreference() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
if (preferences.contains("color")) {
if (preferences.getString("color", "0").equals("1")) {
getWindow().getDecorView().setBackgroundColor(Color.WHITE);
} else if (preferences.getString("color", "0").equals("2")) {
getWindow().getDecorView().setBackgroundColor(Color.BLACK);
} else if (preferences.getString("color","0").equals("3")){
getWindow().getDecorView().setBackgroundColor(Color.RED);
}else{
getWindow().getDecorView().setBackgroundColor(Color.MAGENTA);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.your_item_id) {
//A ovo je metoda za pozivanje i startanje preferences activity-a
Intent intent = new Intent(MainActivity.this, PreferencesScreenActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
private void getUserList() {
try {
APIService service = ApiClient.getRetrofit().create(APIService.class);
Call<List<User>> call = service.getUserData();
call.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
//Log.d("onResponse", response.message());
List<User> userList = response.body();
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.setLayoutManager(layoutManager);
RecyclerViewAdapter recyclerViewAdapter =
new RecyclerViewAdapter(userList);
recyclerView.setAdapter(recyclerViewAdapter);
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
}
});
}catch (Exception e) {}
}
}
So one more time,
I need code to change color of textview item of price from RecyclerViewHolder class.
Thank for all help, every good point of answer will be credited with thanks!
use color as a recyclerview constructor:
int color;
RecyclerViewAdapter recyclerViewAdapter =
new RecyclerViewAdapter(this, userList, color);
//////////////////////////////////////////////////////////////////////////
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder>{
private Context context;
public static List<UserList> userList;
private int color;
public UserAdapter(Context context, List<UserList> userList, int color){
super();
//Getting all the superheroes
this.color = color;
this.userList = userList;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.colorText.setText(mColorText.setText);
//here you will change the text color from mainactivity
// this change color
holder.colorText.setTextColor(ContextCompat.getColor(context,color));
}
#Override
public int getItemCount() {
return 0;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView colorText;
public ViewHolder(View itemView) {
super(itemView);
context = itemView.getContext();
}
}
I didn't really get into your code but I think you could create another TextView in your .xml file with an id like "priceColored" or something.
When you will want to change the price's color, you simply do:
price = itemView.findViewById(R.id.priceColored);
The TextView with the id priceColored will have the color you want to use. If you need to figure out how to create a textview of a certain color in android, you can find it very easily online.
Hope it helps,
In RecyclerViewHolder class make one public method with color arguments and that method used in mainactivity with that class object and call that public method and pass your color code.
Make below method in RecyclerViewHolder.
public void changeColor(int color){
price.setTextColor(color)
}
and call this method in mainActivity
RecyclerViewHolderobject.changeColor(Color.BLACK)
I would like to know how to implement onClick for each item in my
grid (using Recycler View and Card view) to launch a new
activity.Below is my ViewHolder class and the RecyclerView Adapter
Class
This is my RecyclerView Adapter Class
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.nfc.Tag;
import android.nfc.TagLostException;
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.Toast;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {
private List<ItemObject> itemList;
private Context context;
public RecyclerViewAdapter(Context context, List<ItemObject> itemList) {
this.itemList = itemList;
this.context = context;
}
#Override
public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_list, null);
RecyclerViewHolders rcv = new RecyclerViewHolders(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(RecyclerViewHolders holder, final int position) {
holder.countryName.setText(itemList.get(position).getName());
holder.countryPhoto.setImageResource(itemList.get(position).getPhoto());
holder.countryPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(),"This is Maps",Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return this.itemList.size();
}
}
//This is my Recycler View Holder Class
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class RecyclerViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView countryName;
public ImageView countryPhoto;
public RecyclerViewHolders(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
countryName = (TextView) itemView.findViewById(R.id.country_name);
countryPhoto = (ImageView) itemView.findViewById(R.id.country_photo);
}
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "Clicked Country Position = " + getPosition(), Toast.LENGTH_SHORT).show();
}
}
I use Interface as the Callback to handle this case.
First, I create an interface class inside Adapter.
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {
private List<ItemObject> itemList;
private Context context;
private ItemClickListener mItemClickListener;
public RecyclerViewAdapter(Context context, List<ItemObject> itemList) {
this.itemList = itemList;
this.context = context;
}
#Override
public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_list, null);
RecyclerViewHolders rcv = new RecyclerViewHolders(layoutView);
return rcv;
}
public void addItemClickListener(ItemClickListener listener) {
mItemClickListener = listener;
}
#Override
public void onBindViewHolder(RecyclerViewHolders holder, final int position) {
holder.countryName.setText(itemList.get(position).getName());
holder.countryPhoto.setImageResource(itemList.get(position).getPhoto());
holder.countryPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(position);
}
}
});
}
#Override
public int getItemCount() {
return this.itemList.size();
}
//Define your Interface method here
public interface ItemClickListener {
void onItemClick(int position);
}
}
Then, let's the Activity or Fragment implement that Interface and add the listener.
public class MyFragment extends Fragment
implements RecyclerViewAdapter.ItemClickListener {
private List<ItemObject> mItemList;
...
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
...
//Make sure mItemList not NULL
RecyclerViewAdapter adapter = new RecyclerViewAdapter(getContext(), mItemList);
//Add Item Click listener
adapter.addItemClickListener(this);
}
#Override
public void onItemClick(int position) {
Toast.makeText(.getContext(),"Click on item: " + position,Toast.LENGTH_SHORT).show();
}
}
Hope this will help!
your code look like fine, if asking for how to creat intent to open new activity here is whet you should change
it is lazy way not recommended for best pratice
make a static variable in your Mian activty witch is hold a refrance some thing like that
public class MainActivity extends AppCompatActivity
public static Activity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setElevation(0);
activity=this;
}
}
and then inside your click
...
#Override
public void onClick(View v) {
Toast.makeText(.getContext(),"Click on item: " + position,Toast.LENGTH_SHORT).show();
startActivity(new Intent(MainActivity.activity, MyOtherActivity.class));
}
...
I'm not completely clear from your initial post what your issue is, but if all you want to do is implement an OnClickListener in your RecyclerViewAdapter, just add the following:
First, change your class declaration to this:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> implements OnClickListener {
Then, add your onClick method to the class, to complete the interface.
#Override
public void onClick(View view) {
Toast.makeText(this.getContext(),"Code to change activity goes here." ,Toast.LENGTH_SHORT).show();
}
Finally, you'll need to set an OnClickListener in your adapter class.
#Override
public void onBindViewHolder(RecyclerViewHolders holder, final int position) {
holder.setOnClickListener(this);
holder.countryName.setText(itemList.get(position).getName());
holder.countryPhoto.setImageResource(itemList.get(position).getPhoto());
holder.countryPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(position);
}
}
});
}
Now, personally I wouldn't do things this way. What I would do instead is add a private inner class to your adapter, like this:
private AdapterOnClickListener implements OnClickListener() {
private String message;
public AdapterOnClickListener (String toast) {
message = toast;
}
public void onClick (View v) {
Toast.makeText(this.getContext(),toast ,Toast.LENGTH_SHORT).show();
}
}
Then in the adapter you call:
#Override
public void onBindViewHolder(RecyclerViewHolders holder, final int position) {
holder.setOnClickListener(new AdapterOnClickListener ("Instead of a string, I can be an intent. Then in your listener, you can call (If I recall correctly) getContext().startActivity(intent), and have an activity.");
holder.countryName.setText(itemList.get(position).getName());
holder.countryPhoto.setImageResource(itemList.get(position).getPhoto());
holder.countryPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(position);
}
}
});
}
I'm still new with both Java and android
My problem is that the recycleview only gets updated and adds the new added tag if I closed the app and run it again. How can I get the app to update the recycle view instantly to display the new tags.
java code
package com.deitel.favoritesites;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.DialogPreference;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TextInputLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Adapter;
import android.widget.EditText;
import android.widget.TextView;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String SITES="Sites";
private EditText urlEditText; //where user enters the URL
private EditText tagEditText;
private FloatingActionButton saveFloatingActionButton;
private SharedPreferences savedSites;
private List<String> tags;
private SitesAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
urlEditText = ((TextInputLayout) findViewById(
R.id.URLTextInputLayout)).getEditText();
urlEditText.addTextChangedListener(textWatcher);
tagEditText=((TextInputLayout)findViewById(R.id.tagTextInputLayout)).getEditText();
tagEditText.addTextChangedListener(textWatcher);
//get the shared prefrences containing the user saved URLs
savedSites = getSharedPreferences(SITES, MODE_PRIVATE);
//get the shared tags in an ArrayList then sort them
tags = new ArrayList<>(savedSites.getAll().keySet());
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
//get reference to the recycle to configure it
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
//use a linerlayout to display items in a vertical list
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//create recyclerView.Adopter to bind tags to the RecyclerView
adapter = new SitesAdapter(tags, itemClickListener, itemLongClickListener);
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new ItemDivider(this));
//register listner to save a new or edit search
saveFloatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
saveFloatingActionButton.setOnClickListener(saveButtonListener);
updateSaveFAB();
}
private final TextWatcher textWatcher= new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
updateSaveFAB();
}
#Override
public void afterTextChanged(Editable s) {
}
};
//show or hide the saveFloatingActionButton
private void updateSaveFAB() {
//check if there is input in both EditButton
if (urlEditText.getText().toString().isEmpty() || tagEditText.getText().toString().isEmpty())
saveFloatingActionButton.hide();
else
saveFloatingActionButton.show();
}
//saveButtonListener save a tag query pair into sharedPrefrece
private final OnClickListener saveButtonListener=new OnClickListener() {
#Override
public void onClick(View view) {
String query = urlEditText.getText().toString();
String tag = tagEditText.getText().toString();
if (!query.isEmpty() && !tag.isEmpty()) {
//hide the virtual keyboard
((InputMethodManager) getSystemService(
Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(view.getWindowToken(),0);
addTaggedSites(tag, query);//add/update the search
urlEditText.setText("");//Clear queryEditText
tagEditText.setText("");//clear tagEditText
urlEditText.requestFocus();
}
}
};
//add new search to file then refresh all button
private void addTaggedSites(String tag, String query) {
//get a sharedprefrence editor to store new tag/query pair
SharedPreferences.Editor preferencesEditor = savedSites.edit();
preferencesEditor.putString(tag, query);
preferencesEditor.apply();
//if tag is new> add and sort tags then display update
if (!tag.contains(tag)) {
tags.add(tag);
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
adapter.notifyDataSetChanged();
}
}
//itemClickListener launches web broswer to display search results
private final OnClickListener itemClickListener=new OnClickListener() {
#Override
public void onClick(View view) {
//get query string and create a URL represeting the search
String tag= ((TextView) view).getText().toString();
String urlString=getString(R.string.search_URL)+Uri.encode(savedSites.getString(tag,""),"UTF-8");
//create an intent to lanuch a web broswer
Intent webIntent= new Intent(Intent.ACTION_VIEW,Uri.parse(urlString));
startActivity(webIntent);
}
};
//itemLongClickListener displays a dialog allowing the user to share edit or delete a saved search
private final OnLongClickListener itemLongClickListener= new OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
//get the tag that the user long touched
final String tag = ((TextView) view).getText().toString();
//creatw a new AlertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
//set the alertDialog title
builder.setTitle(getString(R.string.share_edit_delete_title, tag));
//set list of items to display and create event handler
builder.setItems(R.array.dialog_items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0://share
shareSites(tag);
break;
case 1://edit
tagEditText.setText(tag);
urlEditText.setText(savedSites.getString(tag, ""));
break;
case 2: //delete
deleteSites(tag);
break;
}
}
}
);
//set the alertDialog negetive button
builder.setNegativeButton(getString(R.string.cancel), null);
builder.create().show();//display the alert dialog
return true;
}
};
//allow user to choose app for sharing URL of a saved search
private void shareSites(String tag){
//create the URL representing the search
String urlString= getString(R.string.search_URL)+Uri.encode(savedSites.getString(tag, ""), "UTF-8");
//create an intent to share urlString
Intent shareIntent= new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_subject));
shareIntent.putExtra(Intent.EXTRA_TEXT,getString(R.string.share_message,urlString));
shareIntent.setType("text/plain");
//display app that can share plain text
startActivity(Intent.createChooser(shareIntent,getString(R.string.share_search)));
}
//delete search after user confirms
private void deleteSites(final String tag){
//create a new AlertDialog and set its message
AlertDialog.Builder confirmBuilder= new AlertDialog.Builder(this);
confirmBuilder.setMessage(getString(R.string.confirm_message, tag));
//cancel button configration
confirmBuilder.setNegativeButton(getString(R.string.cancel), null);
//positive DELETE button
confirmBuilder.setPositiveButton(getString(R.string.delete),new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog , int id){
tags.remove(tag);
//remove sharedPerefrences.Editor from Sharedprefrences
SharedPreferences.Editor preferenceEditor= savedSites.edit();
preferenceEditor.remove(tag);
preferenceEditor.apply();
adapter.notifyDataSetChanged();
}
}
);
confirmBuilder.create().show();
}
}
This is my adopter code
package com.deitel.favoritesites;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class SitesAdapter extends RecyclerView.Adapter<SitesAdapter.ViewHolder> {
private final View.OnClickListener clickListener;
private final View.OnLongClickListener longClickListener;
private final List<String> tags;
public SitesAdapter(List<String> tags, View.OnClickListener clickListener, View.OnLongClickListener longClickListener) {
this.tags = tags;
this.clickListener = clickListener;
this.longClickListener = longClickListener;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView textView;
public ViewHolder(View itemView, View.OnClickListener clickListener, View.OnLongClickListener longClickListener) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.textView);
itemView.setOnClickListener(clickListener);
itemView.setOnLongClickListener(longClickListener);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return (new ViewHolder(view, clickListener, longClickListener));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText(tags.get(position));
}
#Override
public int getItemCount() {
return tags.size();
}
}
Change your code into this
if (!tags.contains(tag)) {
tags.add(tag);
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
adapter.notifyDataSetChanged();
}
Because, this below condition is always false
if(!tag.contains(tag))
Its because you are checking if a value contains in that value itself. SO it will be always true.
If you are checking the tag exist in the List<String> tags you should do like this below.
if(!tags.contains(tag))
change your code to....
//add new search to file then refresh all button
private void addTaggedSites(String tag, String query) {
//get a sharedprefrence editor to store new tag/query pair
SharedPreferences.Editor preferencesEditor = savedSites.edit();
preferencesEditor.putString(tag, query);
preferencesEditor.apply();
//if tag is new> add and sort tags then display update
if (!this.tag.contains(tag)) {
this.tags.add(tag);
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
adapter.notifyDataSetChanged();
}
}
This may help:
create a setter method within your adapter allowing you to set/update the adapter ArrayList.
Whenever you make a change to your list i.e. remove Tag, pass this updated list to your adapter via your new setter method.
call notifyDataSetChanged().
I am trying to call a DialogFragment from my Fragment class. I have an EditText, and would like to call my DialogFragment class in the onClickListener of the EditText I have set up.
I am getting an error in the onClick with the code I have set up trying to call the DialogFragment.
I am getting an error on "show" stating "The method show(FragmentManager, String) in the type DialogFragment is not applicable for the arguments (FragmentManager, String)" and an error on "new Instance" stating "The method newInstance() is undefined for the type MyDialogFragment"
Here's my code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View root = (View) inflater.inflate(R.layout.fragment_profile_fragment, container, false);
setListenerOnWeight(root);
button(root);
return root;
}
public void setListenerOnWeight(View v) {
EditText Weight = (EditText) v.findViewById(R.id.Weight_up);
Weight.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
weight_frag dialog = new weight_frag.newInstance();
dialog.show(getFragmentManager(), "fragmentDialog");
}
});
}
for my DialogFragment class:
package com.the.healthescort;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.*;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class weight_frag extends DialogFragment {
Context mContext;
public weight_frag() {
mContext = getActivity();
}
public static weight_frag newInstance() {
weight_frag f = new weight_frag();
return f;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext);
alertDialogBuilder.setTitle("Set Wallpaper?");
alertDialogBuilder.setMessage("Are you sure?");
//null should be your on click listener
alertDialogBuilder.setPositiveButton("OK", null);
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return alertDialogBuilder.create();
}
}
i think you should replace
import android.app.Fragment;
with
import android.support.v4.app.Fragment;
in your "my Fragment" class
and you should also provide a method with name newInstance in your dialogfragment class like below :
public static weight_frag newInstance(){
weight_frag frag = new weight_frag();
return frag;
}
please follow java naming conventions by using capital letter for the starting letter (WeightFragment)