I need to call a new activity, when a button inside one of my recyclerview row elements is called. Each row item in the list contains 4 buttons, one of which needs to open a new activity which will be used to edit the data in that row.
Here is the code for my button so far:
public void onBindViewHolder(CounterLayoutAdapter.ViewHolder holder, final
int position) {
final Counter counter = counterList.get(position);
//counter is a class which holds the data that will be displayed on one
//row
String comment = counter.getComment();
String name = counter.getCounterName();
int number = counter.getCurrentValue();
//LocalDate modifyDate = counter.getLastModifyDate();
Button up = holder.itemView.findViewById(R.id.buttonUp);
Button down = holder.itemView.findViewById(R.id.buttonDown);
Button reset = holder.itemView.findViewById(R.id.buttonReset);
Button edit = holder.itemView.findViewById(R.id.buttonEdit);
Button delete = holder.itemView.findViewById(R.id.buttonDelete);
// code for 4 other buttons goes here
//
edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
Since I need the activity that I open to return user inputted data for me, I am using startActivityForResult. However, as far as I can tell, this will only work inside an actual activity class.
So then I tried passing the mainactivity context to my CounterLayoutAdapter class, where all of my button code is. However, the OnBindViewHolder method still cannot access it there. So I tried to pass the context to OnBindViewHolder, but that doesn't work either, as it won't override the abstract class if i do that..
So, how on earth can I call a new activity here?
Alternatively, if there is some other way to get user input into 4 fields and return that input back to the adapter, without calling an activity, that would work as well.
EDIT: viewholder and layout inflation
public static class ViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
private TextView name;
private TextView comment;
private TextView number;
//private TextView date;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
comment = itemView.findViewById(R.id.textComment);
name = itemView.findViewById(R.id.textName);
number = itemView.findViewById(R.id.editTextNum);
//date = itemView.findViewById(R.id.textDate);
}
#Override
public void onClick(View view) {}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView =
LayoutInflater.from(parent.getContext()).inflate(R.layout
.row_layout, parent, false);
return new ViewHolder(inflatedView);
}
You can call startActivityForResult() in adapter class.
Get context in adapter like Context context=holder.up.getContext();
then in your button's OnClickListener do this.
edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(context,ActivityYouWantToStart.class);
//Pass any extras if you want to.
((Activity)context).startActivityForResult(intent,REQUEST_CODE);
}
});
Then in your activity (which contain this recyclerView) override onActivityResult like this
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {//same REQUEST_CODE you used in adapter
if (resultCode == RESULT_OK) {
//Do your thing and get the data you want.
adapter.onDataReady(Data data);//where adapter is your recycler adapter,
//and data is whatever data you want to pass to adapter
//(Data you got from the activityResult, do not confuse it with onActivityResult's parameter 'Intent data')
}
}
}
Finally in your Recycler Adapter class, define onDataReady() function like
public void onDataReady(Data data){
//Update RecyclerView with new data
}
Hope this helps. I once did this, and it works for me. Let me know if you have any problem.
As you see , you do not have to findViewById in onBindViewHolder.
public void onBindViewHolder(CounterLayoutAdapter.ViewHolder holder, final
int position) {
final Counter counter = counterList.get(position);
//counter is a class which holds the data that will be displayed on one
//row
String comment = counter.getComment();
String name = counter.getCounterName();
int number = counter.getCurrentValue();
//LocalDate modifyDate = counter.getLastModifyDate();
holder.edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
Then you should init edit in ViewHolder constructor.
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
comment = itemView.findViewById(R.id.textComment);
name = itemView.findViewById(R.id.textName);
number = itemView.findViewById(R.id.editTextNum);
//date = itemView.findViewById(R.id.textDate);
// init four button
edit = itemView.findViewById(R.id.buttonEdit)
}
Related
Hello I want to have an Add function that allows me to input items to my GridView
For Background: I have a standard GridView and an XML activity (which contains 2 TextView) that I want to convert to my GridView. I also have a custom ArrayAdapter class and custom Word object (takes 2 Strings variables) that helps me do this.
My problem: I want to have an Add button that takes me to another XML-Layout/class and IDEALLY it input a single item and so when the user goes back to MainActivity the GridView would be updated along with the previous information that I currently hard-coded atm. This previous sentence doesn't work currently
Custom ArrayAdapter and 'WordFolder' is my custom String object that has 2 getters
//constructor - it takes the context and the list of words
WordAdapter(Context context, ArrayList<WordFolder> word){
super(context, 0, word);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View listItemView = convertView;
if(listItemView == null){
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.folder_view, parent, false);
}
//Getting the current word
WordFolder currentWord = getItem(position);
//making the 2 text view to match our word_folder.xml
TextView title = (TextView) listItemView.findViewById(R.id.title);
title.setText(currentWord.getTitle());
TextView desc = (TextView) listItemView.findViewById(R.id.desc);
desc.setText(currentWord.getTitleDesc());
return listItemView;
}
}
Here is my NewFolder code. Which sets contentview to a different XML. it's pretty empty since I'm lost on what to do
public class NewFolder extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_folder_view);
Button add = (Button) findViewById(R.id.add);
//If the user clicks the add button - it will save the contents to the Word Class
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//make TextView variables and cast the contents to a string and save it to a String variable
TextView name = (TextView) findViewById(R.id.new_folder);
String title = (String) name.getText();
TextView descText = (TextView) findViewById(R.id.desc);
String desc = (String) descText.getText();
//Save it to the Word class
ArrayList<WordFolder> word = new ArrayList<>();
word.add(new WordFolder(title, desc));
//goes back to the MainActivity
Intent intent = new Intent(NewFolder.this, MainActivity.class);
startActivity(intent);
}
});
}
In my WordFolder class I made some TextView variables and save the strings to my ArrayList<> object but so far it's been useless since it doesn't interact with the previous ArrayList<> in ActivityMain which makes sense because its an entirely new object. I thought about making the ArrayList a global variable which atm it doesn't make sense to me and I'm currently lost.
Sample code would be appreciative but looking for a sense of direction on what to do next. I can provide other code if necessary. Thank you
To pass data between Activities to need to do a few things:
First, when the user presses your "Add" button, you want to start the second activity in a way that allows it to return a result. this means, that instead of using startActivity you need to use startActivityForResult.
This method takes an intent and an int.
Use the same intent you used in startActivity.
The int should be a code that helps you identify where a result came from, when a result comes. For this, define some constant in your ActivityMain class:
private static final int ADD_RESULT_CODE = 123;
Now, your button's click listener should looks something like this:
addButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent=new Intent(MainActivity.this, NewFolder.class);
startActivityForResult(intent, ADD_RESULT_CODE);
}
});
Now for returning the result.
First, you shouldn't go back to your main activity by starting another intent.
Instead, you should use finish() (which is a method defined in AppCompatActivity, you can use to finish your activity), this will return the user to the last place he was before this activity - ActivityMain.
And to return some data, too, you can use this code:
Intent intent=new Intent();
intent.putExtra("title",title);
intent.putExtra("desc",desc);
setResult(Activity.RESULT_OK, intent);
where title and desc are the variables you want to pass.
in your case it should look something like this:
public class NewFolder extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_folder_view);
Button add = (Button) findViewById(R.id.add);
//If the user clicks the add button - it will save the contents to the Word Class
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//make TextView variables and cast the contents to a string and save it to a String variable
TextView name = (TextView) findViewById(R.id.new_folder);
String title = (String) name.getText();
TextView descText = (TextView) findViewById(R.id.desc);
String desc = (String) descText.getText();
//Save it to the Word class
ArrayList<WordFolder> word = new ArrayList<>();
word.add(new WordFolder(title, desc));
Intent intent=new Intent();
intent.putExtra("title",title);
intent.putExtra("desc",desc);
setResult(Activity.RESULT_OK, intent);
//goes back to the MainActivity
finish();
}
});
}
You should probably also take care of the case where the user changed his mind and wants to cancel adding an item. in this case you should:
setResult(Activity.RESULT_CANCELLED);
finish();
In your ActivityMain you will have the result code, and if its Activity.RESULT_OK you'll know you should add a new item, but if its Activity.RESULT_CANCELLED you'll know that the user changed their mind
Now all that's left is receiving the data in ActivityMain, and doing whatever you want to do with it (like adding it to the grid view).
To do this you need to override a method called onActivityResult inside ActivityMain:
// Call Back method to get the Message form other Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// check the result code to know where the result came from
//and check that the result code is OK
if(resultCode == Activity.RESULT_OK && requestCode == ADD_RESULT_CODE )
{
String title = data.getStringExtra("title");
String desc = data.getStringExtra("desc");
//... now, do whatever you want with these variables in ActivityMain.
}
}
I want to load the clicked image in the next activity in fullscreen view. I don't know what I am doing wrong. The app is running completely fine but the image is not loading on the next screen. am new to android development and I thought I should start learning by doing a project. I am not understanding what is the problem in my coding.
public class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ImageViewHolder> {
private Context mCtx;
private List<Category> imageslist;
public CategoriesAdapter(Context mCtx, List<Category> imageslist) {
this.mCtx = mCtx;
this.imageslist = imageslist;
}
#NonNull
#Override
public ImageViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(mCtx).inflate(R.layout.recyclerview_images,parent,false);
return new ImageViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ImageViewHolder holder, final int position) {
final Category images=imageslist.get(position);
Glide.with(mCtx).load(images.url).into(holder.imageView);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(mCtx, LoadWall.class);
intent.putExtra("url", (Parcelable) imageslist.get(position));
mCtx.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return imageslist.size();
}
class ImageViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
public ImageViewHolder(#NonNull View itemView) {
super(itemView);
imageView=itemView.findViewById(R.id.image_view);
}
}
}
This is the activity where I want to load the image. But its not loading. Please Help
public class LoadWall extends AppCompatActivity {
ImageView imageView;
int myImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_wall);
imageView=findViewById(R.id.load_image);
get();
}
private void get(){
if(getIntent().hasExtra("url")){
String image=getIntent().getStringExtra("url");
set(image);
}
else{
Toast.makeText(this,"No Data",Toast.LENGTH_SHORT).show();
}
}
private void set(String image){
Glide.with(this).load(image).into(imageView);
}
}
Here you only need to pass URL as a String. Parcelable is not required.
intent.putExtra("url", imageslist.get(position).getUrl());
Option 1)
In your next activity you are looking for String.
String image=getIntent().getStringExtra("url");
in first activity in onClick() change your code to this.
Intent intent=new Intent(mCtx, LoadWall.class);
intent.putExtra("url", imageslist.get(position));
intent.startActivity(intent);
As i see imageslist.get(position) will return Category so you will need to add your url parameter. Something like this imageslist.get(position).getUrl();
Option 2)
If you want to get Category object then in next activity change to this
Category category = getIntent().getParcelableExtra("url");
Your imagesList contains data of type Category and you send an entry from this list to the next activity. However, the second activity expects a String to be received. It will check to see if it has an extra (it has - but not what you need), then try to retrieve that value as a String which will result in a null String. Having null, Glide will not load anything.
In other words, you made a small mistake on what data you use. When you load the data, you do it correctly by using the url field
final Category images=imageslist.get(position);
Glide.with(mCtx).load(**images.url**).into(holder.imageView);
But when you are passing it to the next activity, you send the entire object
intent.putExtra("url", **(Parcelable) imageslist.get(position)**);
Using the url field as you did in the first case will make your app work properly.
Start your Activity
Intent intent=new Intent(mCtx, LoadWall.class);
intent.putExtra("url", images.url);
mCtx.startActivity(intent);
I am new to android development, in fact its my first application. I have created a dynamic layout in my project based on Json. Each object includes an "id" key and some more string keys. every object in my json should be transformed to a cardview inside a recylcerview and each cardview has a button.
My problem is handling these dynamic buttons. Is it possible to determine which button was clicked?
View.id is an integer, and you shouldn't set arbitrary values to it if the View is generated dinamically, what you can use though is View.tag. So you can assign the id defined in the JSON to tag and then check the tag value when the View is clicked. E.g.
val view1 = View(context)
view1.tag = "id from JSON 1"
view1.setOnClickListener(this::onViewClicked)
val view2 = View(context)
view2.tag = "id from JSON 2"
view2.setOnClickListener(this::onViewClicked)
// ...
private fun onViewClicked(view: View){
val jsonId = view.tag as? String
// ...
}
If your min sdk level at least 17, another option would be to generate ids dinamically with View.generateViewId() and store them in a Map together with your JSON ids
Use a Tag to differentiate the buttons. Add OnClickListener to all Button and set different String tag to button.
button.setOnClickListener(this);
Add ClickListener
#Override
public void onClick(View view){
String tag = (String)view.getTag();
if(tag.equals(tag1)){
// action here
}
//.......
.....
}
Yeah pretty straight, all you have to do is to give them a unique id
I assume you must have a JSON array for dynamic buttons creation.
sample code
public Button createButton(Context context,String text,int buttonNo){
//here set the properties
Button bt = new Button(context);
bt.setText(text);
bt.setId(buttonNo);
bt.setTag(buttonNo);
bt.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
//handle the button click, unique id , you can use to differentiate
int id = view.getId();
}
});
return bt;
}
call this above method in for loop or as many times you want to create.
you can also set a tag as mentioned above to store more information.
Finally I put the OnClickListener in onBindViewHolder event inside my customAdapter class as below:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> implements View.OnClickListener {
private Context context;
private List<MyData> my_data;
public CustomAdapter(Context context, List<MyData> my_data) {
this.context = context;
this.my_data = my_data;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card,parent,false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.match_date.setText(my_data.get(position).getMatch_date());
holder.home_name.setText(my_data.get(position).getHome_name());
holder.away_name.setText(my_data.get(position).getAway_name());
holder.button.setId(my_data.get(position).getId());
holder.button.setTag(my_data.get(position).getStringId());
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int intHomeGoals = Integer.parseInt(holder.edtHomeGoals.getText().toString());
int intAwayGoals = Integer.parseInt(holder.edtAwayGoals.getText().toString());
if (intHomeGoals == intAwayGoals)
{
Toast.makeText(context, "00000", Toast.LENGTH_SHORT).show();
}
}
});
Glide.with(context).load(my_data.get(position).getHome_logo()).into(holder.home_logo);
Glide.with(context).load(my_data.get(position).getAway_logo()).into(holder.away_logo);
}
I have an increment system and I want when onClick to save value from DialogAlert in a column in ListView Adapter.
Here is my Adapter:
public class VanzatorProduseList extends ArrayAdapter<VanzatorProduse> {
private Activity context;
private SparseBooleanArray selectedListItemsIds;
private List<VanzatorProduse> vanzatorProduseList;
public VanzatorProduseList(Activity context, List<VanzatorProduse> vanzatorProduseList){
super(context, R.layout.list_produse_vanzator, vanzatorProduseList);
this.context = context;
selectedListItemsIds = new SparseBooleanArray();
this.vanzatorProduseList = vanzatorProduseList;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list_produse_vanzator, null, true);
TextView textViewProdus1 = (TextView) listViewItem.findViewById(R.id.textViewProdus1);
TextView textViewPret1 = (TextView) listViewItem.findViewById(R.id.textViewPret1);
final TextView textViewCantitate1 = (TextView) listViewItem.findViewById(R.id.textViewCantitate1);
final VanzatorProduse vanzatorProduse = vanzatorProduseList.get(position);
textViewProdus1.setText(vanzatorProduse.getProdus());
textViewPret1.setText(vanzatorProduse.getPret());
textViewCantitate1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.dialog_alert);
dialog.setTitle("Alege Canitatea");
// set the custom dialog components - text, image and button
final Button dialogBtn = (Button) dialog.findViewById(R.id.dialog_btn);
final ElegantNumberButton elegantNumberButton = (ElegantNumberButton) dialog.findViewById(R.id.elegantNumberButton);
// if button is clicked, close the custom dialog
dialogBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
dialog.dismiss();
}
});
dialog.show();
}
});
return listViewItem;
}
Here is what I tried but I got an error and no idea what to do next :
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
Error:
'add(com.dev.darius.neglije.Vanzator.ListaProduse.VanzatorProduse)' in 'java.util.List' cannot be applied to '(java.lang.String)'
Here I'm stuck I want to display in TextView called textViewCantitate1.
Hope you understand.
As stated in earlier answers by #jibrahim:
You are trying to add String type into List vanzatorProduseList. You can add only VanzatorProduse type into vanzatorProduseList list. So, the cause of the problem is:
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
You need to do something like this Create Object of your Custom class and assign value to that:
String num = elegantNumberButton.getNumber();
VanzatorProduse numVanProObject = new VanzatorProduse();
numVanProObject .setNumber(num );
vanzatorProduseList.add(numVanProObject );
But your custom call should have method to cater this type issue
Edit: Do not forget to call notifyDataSetChanged() method to refresh the list
VanzatorProduse producse = new VanzatorProduse();
producse.setProdus("add value here")
vanzatorProduseList.add(producse);
You are trying to add String type into List<VanzatorProduse> vanzatorProduseList. You can add only VanzatorProduse type into vanzatorProduseList list. So, the cause of the problem is:
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
In your code you have following lines:
final VanzatorProduse vanzatorProduse = vanzatorProduseList.get(position);
textViewProdus1.setText(vanzatorProduse.getProdus());
textViewPret1.setText(vanzatorProduse.getPret());
So, might be you add num value into vanzatorProduse.setProdus(num) or any other appropriate field and then add it into the list:
vanzatorProduseList.add(vanzatorProduse);
I'm currently following this tutorial to implement a shared element transition between view (cards) in RecyclerView and activity but I'm not sure how can I do it since I'm using an onClickListener on MyRecyclerAdapter class to start a new activity.
Just new in development, hope you can help me about it.
MyRecyclerAdapter.java
public class MyRecyclerAdapter extends RecyclerView.Adapter<PaletteViewHolder> {
private Context context;
private List<Palette> palettes;
public MyRecyclerAdapter(Context context, List<Palette> palettes) {
this.palettes = new ArrayList<Palette>();
this.palettes.addAll(palettes);
this.context = context;
}
#Override
public PaletteViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.card_view, viewGroup, false);
itemView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(context, ScrollingActivity.class);
intent.putExtra("P25", "Longanissa");
context.startActivity(intent);
}
});
return new PaletteViewHolder(itemView);
}
#Override
public void onBindViewHolder(PaletteViewHolder paletteViewHolder, int i) {
Palette palette = palettes.get(i);
paletteViewHolder.titleText.setText(palette.getName());
paletteViewHolder.contentText.setText(palette.getHexValue());
paletteViewHolder.card.setCardBackgroundColor(palette.getIntValue());
}
#Override
public int getItemCount() {
return palettes.size();
}
animateIntent method:
public void animateIntent(View view) {
// Ordinary Intent for launching a new activity
Intent intent = new Intent(this, YourSecondActivity.class);
// Get the transition name from the string
String transitionName = getString(R.string.transition_string);
// Define the view that the animation will start from
View viewStart = findViewById(R.id.card_view);
ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation(this,
viewStart, // Starting view
transitionName // The String
);
//Start the Intent
ActivityCompat.startActivity(this, intent, options.toBundle());
You need to set the transition name of the view inside the onBindViewHolder. It needs to be different of the others viewHolder so get a way to make it different and unique (using palette.getName() if palette names are unique for example or use i).
Then you need to start the activity inside on click using the provided view:
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(context, v, v.getTransitionName());
context.startActivity(intent, options.toBundle());
I don't understand why you need animateIntent method. Hope it still helps