I've got a card-view that each card has a button on it. I'm trying to get the position of the card that holds the button when the users clicks the button.
I have an adapter that extends from RecyclerView.Adapter and implements the following method...
public void onBindViewHolder(MovieImageViewHolder movieImageViewHolder, int i) {
Movie movieItem = mMovieList.get(i);
movieImageViewHolder.details.setTag(i);
movieImageViewHolder.details.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
position = (Integer) v.getTag();
}
});
}
This works sucessfully, when I press a button on card 1, position equals 1 and when I press a button on card 4, position equals 4.
The question is, how do I get this value (position) out of the adapter and back into the Activity so I can use it? or do I even need to do that? I'm trying to create a new intent but don't think that should be done from the adapter?
I attempted to create a getter for the variable position, and call the primary button action with
public void buttonClick(View view) {
int position = adapter.getPosition();
Log.d(TAG, "Button Clicked::- " + String.valueOf(position));
}
Using
android:onClick="buttonClick"
In the XML, but nothing happens when clicking the button, I believe this is because the OnClick method in the adapter is fired instead?
EDIT:
Seems I've made some progress. Worked out that I can set the tag in the adapter
movieImageViewHolder.btn_details.setTag(i);
Then get that tag back in my onClick method with .getTag();
Only thing now is the tag seems to be zero for the first element, then zero for the second element, then starts at one for the third... Any reason why this would be?
This was actually very simple and a very common "issue" people face. I was set down the path that I couldn't create an activity from an adapter where infact that is exactly what I should have been trying to do.
movieImageViewHolder.details.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
Integer taggedPosition = (Integer) v.getTag();
Intent intent = new Intent(mContext, ViewMovieDetailsActivity.class);
intent.putExtra(SearchMovie.MOVIE_TRANSFER, getMovie(taggedPosition));
v.getContext().startActivity(intent);
}
});
Correctly starts the correct activity.
Related
Currently: i have a recycler view where it has delete button and an edit text for each item.
Each item in the recycler view contains edit text that the user can input.
The scenario is i have 4 item in the list resulting 4 edit text.
When i try to fill up edit Text in the item(n) and tried to delete
the item(n) and add again. The edit Text value in the edit text remains.
How can i clear the value of the edit text?
Here is my current code when i try to delete a specific item in the list:
mHeaderText.remove(pos);
ArrayList<Integer> temp = new ArrayList<Integer>();
for (int i = 1 ; mHeaderText.size() >= i ; i++) {
temp.add(i);
Log.d("ADDDING","ADDDING"+i);
}
mHeaderText.clear();
mHeaderText.addAll(temp);
notifyDataSetChanged();
Try this code ..
In adapter class in onBindView method when you perform click event then set edittext value as null.
edittext.setText("");
and if your edittext box in activity layout then make interface into adapter class and handling click event like this way...
OnItemClick onItemClick;
public void setOnItemClick(OnItemClick onItemClick) {
this.onItemClick = onItemClick;
}
public interface OnItemClick {
void getPosition(String data); //pass any data to shared it.
}
after that..
#Override
public void onBindViewHolder(ItemViewHolder holder, final int position) {
// below code handle click event on recycler view item.
final String data = mStringList.get(position);
holder.textView.setText(data);
holder.firstButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClick.getPosition(data); // shared data.
}
});
}
after that in activity adapter bind into recycler view it means adapter not null then called below line..
adpater.setOnItemClick(new RecyclerViewAdpater.OnItemClick() {
#Override
public void getPosition(String data) {
// hear perform any operation.
editTextbox.setText("");
adpater.notifyDataSetChanged();
}
});
Use
edittext.setText("");
to clear text where edittext is reference to EditText. Since you haven;t posted complete code so i can guide to this only. If you provide more code, then I can help you more.
One thing is sure. You will need to use
edittext.setText("") to clear the value.
But you need to be careful. You need to keep this as the first line in your delete row function, i.e. before you are removing that edittext item from your list.
Here is my code: I have placed the "remove row" function inside onBindViewHolder() method of Recyclerview Adapter.
holder.delImgView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// You need to place it in the start
holder.editText.setText("");
// Remove the item on remove/button click
myArrayList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, myArrayList.size());
Toast.makeText(context, "Removed : " + position +" item", Toast.LENGTH_SHORT).show();
}
});
I am using AndroidSwipeableCardStack to do a tinder like interface with a 5 star rating system. When I click on a button that is meant to change the image. The image changes three cards later not in the current card.
This is the project I used: https://github.com/wenchaojiang/AndroidSwipeableCardStack
I assume it is to do with it pre-loading the next card as a recyclerview normally does but I am really not sure.
This my adapter below, you can see at the bottom I call setimageresource on the one star rating image button onclicklistner. I set a Log.d and the button click is registering immediately upon click but the change in the image resource appears only after 3 cards have been swiped.
Edit: So I noticed that regardless of the project I imported, my adapter is only extending ArrayAdatper. So I guessed that the problem might be in the getView method and that I might need to override something else (not sure). But the important point, I checked the position in getView by logging the position and sure enough it said position 0,1,2,3 without anything being swiped away. This is analogous to the offset of the setImageResource so I believe they are interlinked but unfortunately that doesn't bring me any closer to an answer.
Thanks for your help.
public class SongPreviewCardsDataAdapter extends ArrayAdapter<SongDatabaseMappingAdapter> {
public SongPreviewCardsDataAdapter(Context context, int resource) {
super(context, resource);
}
ImageButton oneStarRating;
#Override
public View getView(int position, final View contentView, ViewGroup parent) {
// Initialise Song Views
SongDatabaseMappingAdapter item = getItem(position);
TextView songName = (TextView) (contentView.findViewById(R.id.songNameTextView));
songName.setText(item.getSongTitle());
com.mikhaellopez.circularimageview.CircularImageView songImage = (CircularImageView) contentView.findViewById(R.id.songImageView);
String ImageURL = (item.getPictureURL());
Picasso
.with(this.getContext())
.load(ImageURL)
.into(songImage);
// Initialise Rating Buttons
oneStarRating = (ImageButton) contentView.findViewById(R.id.ratingButton1);
// Create OnClickListners for Ratings Buttons
oneStarRating.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
oneStarRating.setImageResource(R.drawable.starfull);
Log.d("Star", "Star Clicked");
}
});
return contentView;
}
}
getView can be called at any time on any item, so if you want something to stay set on a view, you have to model it.
I don't know if your SongDatabaseMappingAdapter class is something you can change or not, but I'll assume you can change it.
Add a variable to your item class, like boolean mOneStar. Getter/setter left as an exercise for the reader.
In getView() make your item final so you can refer to it in the onClick callback:
final SongDatabaseMappingAdapter item = getItem(position);
Use the variable in getView to set up your view:
oneStarRating = (ImageButton) contentView.findViewById(R.id.ratingButton1);
oneStarRating.setImageDrawable(null); // clear out recycled value
if (item.isOneStar()) {
oneStarRating.setImageResource(R.drawable.starfull);
}
In your OnClickListener, set the property on the item and call notifyDataSetChanged():
oneStarRating.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Star", "Star Clicked");
item.setOneStar(true);
notifyDataSetChanged();
}
});
The main point is: Never change a view from an event handler. Always change the item from the event handler then call adapter.notifyDataSetChanged(), and always change your view in getView() based on the item.
So I have images in gridview. These images are shown in an activity. When one of the images is clicked, new activity is started with this image. In this activity, If user inputs correct answer, new activity is started that indicates the answer is correct. After user inputs correct answer, I want to set this image more transparent with a check mark in gridwiew. If the user clicks again to this correct view, I want to show same activity which indicates it was solved correct. How can I do that?
Here is my activity which contains grid view:
public class LogoSelectionActivity extends Activity {
.
.
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Intent intent = new Intent(LogoSelectionActivity.this, LogoActivity.class);
intent.putExtra ("clicked_position", position);
startActivity(intent);
}
Here is my activity where user enter inputs:
public class LogoActivity extends Activity{
EditText text;
Button check;
Boolean a;
int id;
Names name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logo);
check = (Button) findViewById(R.id.Check_button);
text = (EditText) findViewById(R.id.editText1);
ImageView view = (ImageView)findViewById(R.id.imageView1);
final ImageView incorrect = (ImageView)findViewById(R.id.incorrect);
switch (getIntent().getIntExtra ("clicked_position", -1))
{
case 0:
view.setImageResource(R.drawable.adese);
id = R.drawable.adese;
break;
case 1:
view.setImageResource(R.drawable.birvar);
id = R.drawable.birvar;
break;
case 2:
view.setImageResource(R.drawable.agaoglu);
break;
case 3:
view.setImageResource(R.drawable.akinsoft);
break;
default:
view.setImageResource(R.drawable.afra);
id = R.drawable.afra;
}
name = Names.forDrawable(id);
check.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
a=name.isCorrect(text.getText().toString());
if(a==true){
Intent intent = new Intent(LogoActivity.this, CorrectActivity.class);
startActivity(intent);
}
else{
incorrect.setVisibility(0);
incorrect.setVisibility(4);
}
}
});
}
}
I hope I could explain my intention clearly.
There are number of ways to do this. Because this is not problem this is functionality that you want in your project.
According to my logic I am giving you one solution.
Steps:
Create one static array with the length of your items in grid view with default value is 0.
static int[] items = {0,0,0,...};
Now check in getView methode of grid view with the value according to position in array that if it is 0 then it will looks like normal otherwise it will look with different (Here you want transparent with check box this will you get by adding one more image on it.)
If(items[position] == 0){
}else{
}
Now when user taps any image and navigate to other screen (Suppose Activity B) that time pass value of that position from that array and check in Activity B's OnCreate().
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Intent intent = new Intent(LogoSelectionActivity.this, LogoActivity.class);
intent.putExtra ("clicked_position", position);
intent.putExtra ("answered_or_not", items[position]);
startActivity(intent);
}
And if answered means if its value is 1 then show accordingly other wise as it is.
And when it user give answer unanswered question make its value 1 in that array.
I hope it will help you can ask if any question.
Depending on the clicked button out of 3 button, different data gets populated in listView.
I've used this
onListItemClick snippet
//ltable refers to list
String item = ltable.getItemAtPosition(position).toString();
Intent i = new Intent(getApplicationContext(),NextClass.class);
i.putExtra("name", item);
startActivity(i);
Now on any button click, corresponding data gets populated in listView. Then on listItelClick, it navigates to NextClass.class and hence new activity gets launched.
What if I want app to navigate to next view if and only if listView is populated when Gainers or Losers button is pressed????
If listView is populated on Index button click, it should not navigate.
i.e. Clicked button should be captured.
I tried to use flag, but only final variables are permitted within buttonClickListener, so it doesn't work.
How can I implement this??
ANY HELP WILL BE LIFE-SAVER !!!
Take a class level variable
boolean shouldNavigate = false;
and in onClick() of Index Button. set shouldNavigate to false:
public void onClick(View v)
{
// Update adapter for Index..
shouldNavigate = false;
}
But in onClick() of other than Index Button. set shouldNavigate to true:
public void onClick(View v)
{
// Update adapter for Gainer or Losers..
shouldNavigate = true;
}
and inside your onItemClick() check for the flag and navigate accordingly
public void onItemClick(AdapterView parent, View view, int position, long id) {
if(shouldNavigate)
{
// you can navigagte...
}
else
{
// do other task
}
}
When you are in the 'Index' mode, remove the onItemClickListener. Add it back for the other two buttons.
I'm developing one android application in which I'm using one customized ListView which extends BaseAdapter, In which I have placed two TextView's and one button to delete the corresponding row from the list and also from the original data,
Whenever I call the notifyDataSetChanged() function the value of the position get reversed, am I doing anything wrong ?, Is there any other correct way to do this without the position get reversed ?
convertView.setOnClickListener(new OnClickListener() {
private int pos = position;
public void onClick(View v) {
Toast.makeText(context, "Click-" + String.valueOf(pos), Toast.LENGTH_SHORT).show();
}
});
holder.delete.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
adapter.notifyDataSetChanged();
}
});
Any help will be appreciated.
Instead of on click for button in the every row in the list I just used context menu and performed the actions needed and updated the list and now its working.
Actually this is not the solution for my question and its just an alternative.