How to change text button when click in adapter
I try it's not work
public void setQuestData(final ViewHoder viewHoder, final int position) {
viewHoder.btn_select_qq.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!profileFeedListModelTwos.get(position).getStatus_select().equalsIgnoreCase("SELECTED")){
viewHoder.btn_select_qq.setText("Accepted");
notifyDataSetChanged();
}
notifyDataSetChanged();
}
});
How to fix it ? and where is my problem?
Do not handle the click event inside the adapter class , instead handle it in the fragment using BaseRecyclerViewAdapter.OnRecyclerViewInteractionListener() or adapter listener of the adapter that you are using.
Set position as a tag inside your adapter then use it get the item in your fragment.
Make your adapter extend BaseRecyclerViewAdapter or adapter that you are using
Basic Idea
adapter = new Adapter(enter code here for setting click listener)
Inside YourAdapter just set the clickListener to your view
viewHoder.btn_select_qq.setOnClickListener(this)
Inside your fragment handle the action on click
YourAdapter adapter = new YourAdapter(getActivity(),new BaseRecyclerViewAdapter.OnRecyclerViewInteractionListener() {
#Override
public void onClick(View view) {
int position = (int) view.getTag();
ItemObject item =adapter .getItem(position);
switch (view.getId()) {
case R.id.view1:
//TODO write logic here
break;
case R.id.view2:
//TODO write logic here
break;
case R.id.view3:
//TODO write logic here
break;
}
}
});
Related
I want to detect each item in my RecylerView after it is displayed to the user.
Basically, I am trying to play a sound on each item after it is loaded on the screen.
But I am not able to detect whenever each item is loaded on the screen! Is there any method I have to call to detect each item rendered
E.g 1st RecyclerView item displayed -> play sound
2st RecyclerView item displayed -> play sound...
My Adapter class looks like this -
public class AdapterListAnimation extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Multiples> items = new ArrayList<>();
private Context ctx;
private OnItemClickListener mOnItemClickListener;
private int animation_type = 0;
.........
.........
I am calling this initComponent() method from onCreated() method. Can you give advice on what should I do to achieve my goal as described above?
private void initComponent() {
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
items = DataGenerator.getPeopleData(this,of,value);
setAdapter();
/* MediaPlayer mp=MediaPlayer.create(this, R.raw.sword);
if (mp.isPlaying()) {
mp.stop();
mp.release();
mp = MediaPlayer.create(this, R.raw.sword);
} mp.start();*/
}
private void setAdapter() {
// Set data and list adapter
mAdapter = new AdapterListAnimation(this, items, animation_type);
recyclerView.setAdapter(mAdapter);
// on item list clicked
mAdapter.setOnItemClickListener(new AdapterListAnimation.OnItemClickListener() {
#Override
public void onItemClick(View view, com.math.multiplication.model.Multiples obj, int position) {
Snackbar.make(parent_view, "Item " + obj.first + " clicked", Snackbar.LENGTH_SHORT).show();
}
});
}
you need to override onViewAttachedToWindow and onViewDetachedFromWindow. but for detecting holer type you need getItemViewType() just like that:
public class PostAdapter extends RecyclerView.Adapter {
#Override
public int getItemViewType(int position) {
switch (types.get(position)){
case 1:
return 1;
case 2:
return 2;
default:
return position;
}
}
#Override
public void onViewAttachedToWindow(#NonNull RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
if (holder.getItemViewType() == 1){
//play song
}
}
#Override
public void onViewDetachedFromWindow(#NonNull RecyclerView.ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
if (holder.getItemViewType() == 1){
//pause song
}
}
You need to add listener for TTS. Then update your RecyclerView to show right image when speech starts and ends.
I've created a test project to show how it can be implemented. Here you can see how it works. Here is my github repository.
Here is main part of my MainActivity class.
private void initTts() {
tts = new TextToSpeech(this, this);
tts.setLanguage(Locale.US);
tts.setOnUtteranceProgressListener(new MyListener());
}
#Override
public void onInit(int status) {
playSound(0);
}
private void playSound(int index) {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, String.valueOf(index));
tts.speak(data.get(index), TextToSpeech.QUEUE_ADD, hashMap);
}
class MyListener extends UtteranceProgressListener {
#Override
public void onStart(String utteranceId) {
int currentIndex = Integer.parseInt(utteranceId);
mMainAdapter.setCurrentPosition(currentIndex);
handler.post(new Runnable() {
#Override
public void run() {
mMainAdapter.notifyDataSetChanged();
}
});
}
#Override
public void onDone(String utteranceId) {
int currentIndex = Integer.parseInt(utteranceId);
mMainAdapter.setCurrentPosition(-1);
handler.post(new Runnable() {
#Override
public void run() {
mMainAdapter.notifyDataSetChanged();
}
});
if (currentIndex < data.size() - 1) {
playSound(currentIndex + 1);
}
}
#Override
public void onError(String utteranceId) {
}
}
You can simply use onViewAttachedToWindow(VH) in your adapter.
See https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow(VH)
Update:
As you know RecyclerView will be call OnBindViewHolder only once for each item.
RecyclerView will not call this method again if the position of the item changes in the data set unless the item itself is invalidated or the new position cannot be determined.
So you can use onViewAttachedToWindow
(onViewAttachedToWindow) Called when a view created by this adapter has been attached to a window.
This can be used as a reasonable signal that the view is about to be seen by the user. If the adapter previously freed any resources in onViewDetachedFromWindow those resources should be restored here.
You can use it like this:
public class Adapter extends RecyclerView.Adapter<MyViewHolder> {
// rest of your code
#Override
public void onViewAttachedToWindow(MyViewHolder holder) {
super.onViewAttachedToWindow(holder);
// play your sound
}
}
Hope it helps!
If I understood your problem correctly, you want to play a sound when an item in the RecyclerView is loaded.
Hence I would like to think of a workaround here. You might consider having an item added after the sound for the previous item has been played.
I would like to provide a pseudo code for what I am trying to explain. You might consider using the MediaPlayer.OnCompletionListener for listening if your sound has stopped playing and then add the next item to the RecyclerView and then call notifyDataSetChanged on your adapter to load the next item in your RecyclerView.
Hence you might want the following modification in your adapter first.
// Declare a function in your adapter which adds new item in the RecyclerView
public void addItem(Multiples item) {
items.add(item);
notifyItemInserted(items.size());
}
Now in your Activity where you set up the RecyclerView, you need to have the following arrays.
ArrayList<Multiples> allItems = new ArrayList<Multiples>(); // This list will contain all the data
int soundToBePlayed = -1; // Initialize the value with -1
ArrayList<Integer> soundList = getAllSoundsInAList();
Modify your functions as follows.
private void initComponent() {
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
allItems = DataGenerator.getPeopleData(this,of,value);
setAdapter();
}
private void setAdapter() {
mAdapter = new AdapterListAnimation(this, animation_type); // Do not pass the items list
recyclerView.setAdapter(mAdapter);
// .. Your item click listener goes here
}
As the items was removed from the constructor, you need to modify the constructor of your adapter as well. Just remove the variable which takes the items. Because we will be adding elements to the items later.
Then you need to write another function which needs to be called in your onCreate function of your activity after your call your initComponent function. The function should look like the following.
private void addItemInRecyclerViewAndPlaySound() {
soundToBePlayed++;
adapter.addItem(allItems.get(soundToBePlayed));
recyclerView.scrollToPosition(adapter.getItemCount() - 1);
Integer soundId = soundList.get(soundToBePlayed);
MediaPlayer mp = MediaPlayer.create(this, soundId);
if (mp.isPlaying()) {
mp.stop();
mp.release();
mp = MediaPlayer.create(this, soundId);
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// Call this function again to add next item
// and play the next sound at the same time
if(soundToBePlayed < allItems.size() - 1)
addItemInRecyclerViewAndPlaySound();
}
});
}
mp.start();
}
I have not tested the code, however, I think you get the idea already. This can be implemented gracefully using a interface inside the adapter as well. The imeplemntation technique is your choice.
This question already has answers here:
Android : How to set onClick event for Button in List item of ListView
(10 answers)
Closed 4 years ago.
I'm making an inventory tracker app for Android for a practice project. I use SQLite for the storage and my ListView displays the contents of the database using a CursorAdapter. I use CursorLoader to fetch the data from the database
Each row in my ListView has a couple of TextViews and a Button. I plan to use the Button to decrement the quantity column/property of the selected item in the database.
Where do I setup the button OnClick listener? In my Activity class or my CursorAdapter class' bindView()?
Also how can I detect which row the button was pressed on from the button click?
I've already used the ListView's onItemClickListener to send the user to a detailed Activity that display more info about the current row. That had an id argument that gets passed. So I'm finding an equivalent that I can use for the buttons I put on each row.
Look the following. I used the Custom adapter to add the onItemClickListener:
private class MyListAdapter(val ctx: Context, val values: List<MyListInformatin>) : ArrayAdapter<MyListInformatin>(ctx, -1, values) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val rowView = inflater.inflate(R.layout.item_my_layout, parent, false)
rowView.setOnClickListener {
val detailsActivity = Intent(ctx, DetailsActivity::class.java)
detailsActivity.putExtra(DetailsActivity.ROUTE_NUMBER_PARAM, values.get(position).routeNumber)
val bundle = Bundle()
bundle.putParcelable(detailsActivity.ROUTE_NO_STRUCTURE_PARAM, values.get(position).strucutre)
detailsActivity.putExtra(detailsActivity.PARAM_BUNDLE, bundle)
ctx.startActivity(detailsActivity)
}
return rowView
}
}
You can create an interface inside your adapter and a declare a fucntion in this interfae like ** void itemClick(int position)** and implement that interface in your activity
for void itemClick(int position) method :- Define it on
holder.setOnClickListener() block like -
viewHolder.button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (yourInterface != null) {
yourInterface.itemClick(position);
}
}
});
For detailed description refer the below link -
https://www.c-sharpcorner.com/UploadFile/9e8439/create-custom-listener-on-button-in-listitem-listview-in-a/
This question has been answered already, you need to setup your list items as not clickable and manually listen for onClick events of buttons, see a detailed answer here: Android : How to set onClick event for Button in List item of ListView
public class MyCustomAdapter extend Adapter {
private MyOnClickListener mListener;
#Override
public View getView(int position, View view, ViewGroup parent)
{
...
// Your view
mContainer.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
mListener.onWholeItemClick(position);
}
});
// Your button
mButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
mListener.onButtonClick(position);
}
});
}
public void setListener(MyOnClickListener listener) {
this.mListener = listener;
}
// Listener interface
public interface MyOnClickListener() {
void onWholeItemClick(int position); // Can pass data as a parametter
void onButtonClick(int position);
}
}
public class MyActivity extend Activity implement MyOnClickListener() {
...
#Override
public void onCreate(...) {
mAdapter = new MyCustomAdapter(this);
mAdapter.setListener(this); // Pass the listener to adapter
}
#Override
public void onWholeItemClick(int position) {
//
}
#Override
public void onButtonClick(int position) {
//
}
}
That how you can fully hanhle click events
In onBindViewHolder give a tag to that button. that tag can be the position of item or the item itself . ( tag can be object )
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
CUSTOMMODEL item = items[position];
...
holder.button.setTag(item);
//OR
holder.button.setTag(position);
...
holder.button.setOnClickListener(clickListener);
}
in your onClick(View view) method, get tag from the view and you can understand which item is clicked.
I am new to the fragment.
in Activity, I have two onClick methods which are:
click that override the method
normal onclick
how can I change the onclick that override the method to fragment?
private void searchMobileNumber() {
mRecyclerView.addOnItemTouchListener(new SelectExistingOrNewNoFragment.RecyclerTouchListener(PostpaidRegistrationActivity.this, mRecyclerView, new SelectExistingOrNewNoFragment.ClickListener() {
#Override
public void onClick(View view, int position) {
selectedPostion = position;
mob_number_detail_lyt.setVisibility(View.GONE);
mobile_no_head_lyt.setVisibility(View.VISIBLE);
mobile_number_success.setImageDrawable(getResources().getDrawable(R.drawable.validation_correct));
if (simCardFirstTime) {
simCardFirstTime = false;
final Intent intent = new Intent(PostpaidRegistrationActivity.this, MyScanActivity.class);
intent.putExtra("ocrType", "Barcode");
intent.putExtra("message", "Please scan your SIM card");
startActivityForResult(intent, MposConstants.SIMCARD_FIRST_TIME);
}
}
}
If I get this clear, you have two buttons. One of which is to start a fragment or do something with it.. You just need a switch case. Also, use the R class for the cases.
Use view.getId()
Code:
#Override
public void onClick(View view, int position) {
switch(view.getId()){
case R.id.fragment_button:
// do something with fragment
break;
default: break;
}
}
I'm working on simple android project that require spinner widget in android studio. what i want to do is, when a user select choices from the spinner it will open another activity. while i'm in the middle of the coding. I decided to use switch case condition with Intent. The problem is whenever i run the application it will automatically go to the specific activity location that i declare. Even though I didn't select any choice on spinner.
Note: log cat doesn't show any error
Your help is very much appreciated to beginner like me.
public class CustomOnItemSelectedListener extends Activity implements
OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos,
long id) {
// **************************** below here is where I start the new activity
switch (pos) {
case 0 :
Intent i = new Intent(app.this, home.class);
app.this.startActivity(i);
break;
case 1 :
//Intent intent = new Intent(app.this, about.class);
//app.this.startActivity(intent);
break;
case 2 :
//Intent intent1 = new Intent(app.this, home.class);
//app.this.startActivity(intent1);
break;
}
// **************************** above here is where I start the new activity
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
Try this
Declare an int in your class, e.g. before onCreate(), then in your onCreate() you assign it to 0. Use this variable to check if its bigger than 0 when selecting something with your spinner, example below.
public class ExampleActivity extends AppCompatActivity {
private int spinnerCheck;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSpinnerCheck = 0;
mMySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int itemId = (int) id;
// For some reason this method is called during initialization, so increment counter once to prevent it from auto selecting first item when loading view
spinnerCheck += 1;
if (spinnerCheck > 1) {
switch (pos) {
case 0:
Intent i = new Intent(app.this, home.class);
app.this.startActivity(i);
break;
case 1:
//Intent intent = new Intent(app.this, about.class);
//app.this.startActivity(intent);
break;
case 2:
//Intent intent1 = new Intent(app.this, home.class);
//app.this.startActivity(intent1);
break;
}
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
For some reason it selects the first item once created, not sure why, but this should work.
When the application is created by default the first option is selected in your spinner and your listener is called. To avoid this you can use the solution of #Simon
or you can use a button to confirm your selection and change your activity when this button is pressed and not when an item is selected in your spinner.
UPDATE
You can also populate the first entry of your spinner with a useless text which can be a title like "Select activity" and start your switch in the listener to 1 and not 0
Always in my apps I added buttons in void onCreate, but now I'm trying to do app with more buttons (about 10). I would like to all buttons active on start app.
In my opinion it is too much buttons to add in this onCreate and app will be starting to long.
I tried to put this:
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
})
out of onCreate
but AndroidStudio underlines setOnClickListener and view
I don't have ideas, how and where can i add button out of onCreate.
If you don't want to overcrowd your oncreate method, then create a clicklistener outside onCreate anywhere in activity and in onCreate just set it.
onCreate :
edit_a_member = (Button) findViewById(R.id.edit_member);
delete_a_member = (Button) findViewById(R.id.delete_member);
edit_a_member.setOnClickListener(handleClick);
delete_a_member.setOnClickListener(handleClick);
clickListener:
private View.OnClickListener handleClick = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit_member:
member_selected = EDIT_MEMBER_SELECTED;
callDialog();
break;
case R.id.delete_member:
callDeleteAlert();
break;
}
}
};
You can simply add a separate method for your buttons in the same class, e.g.:
public void onCreate(...){
//Standard setup of views or whatever you want to do here
this.addButtons();
}
private void addButtons(){
Button b1 = new Button("Hi");
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
Button b2 = new Button("Hi to you too");
b2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
}
This is an example. You can do this in soooo many ways. I feel like you should thoroughly learn Java's fundamental Object Oriented programming, because that's really what your question suggests you don't understand. Go follow a youtube tutorial. I always like "The New Boston"'s Java tutorial series on youtube.
PS: You can make code like this beautiful under the 'Words of wisdom': Don't repeat yourself
If you have to do a lot of work in your onCreate but you are worried that the UI will take too long to load you can always post a delayed runnable to a handler so in the onCreate method put :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//add your code here
}
},10);
what this will do is your UI will load then the code in your Runnable will be executed 10 milliseconds after your UI loads thus your app will not take too long to load the UI, even though in your case I doubt it would be necessary.
If you are declaring the buttons in xml file :
Add these properties in each button Declaration in your Xml :
android:clickable="true"
android:onClick="onClick"
And now in Activity Class create a method like this :
public void onClick(View v){
switch(v.getId){
case R.id.{buttons_id_in_xml}
(Your Code)
break;
(Like for others)
}
}
If you want to add buttons dynamically :
Create a method to add the button like this:
void addButton(String buttonName, int button id){
Button button = new Button(this);
button.setText("Push Me");
(add it to parent Layout of xml)
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(id){
case id1:
(handle )
break;
(like for others)
}
}
});
}
The best way to do this is:
add implements View.OnClickListener to
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// declare variables
private Button mBtn1;
private Button mBtn2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
// make an instance to the btns
mBtn1 = findViewById(R.id.btn1);
mBtn2 = findViewById(R.id.btn2);
// set onClickListener
mBtn1.setOnClickListener(this); // with "this" you are passing the view
mBtn2.setOnClickListener(this);
}
// implement onClick
#Override
public void onClick(View view) {
// check which btn was clicked by id
switch (view.getId()) {
case R.id.btn1:
btn1Clicked();
break;
case R.id.btn2:
btn2Clicked();
break;
}
}
private void btn1Clicked() {
// your code btn1 clicked
}
private void btn2Clicked() {
// your code btn2 clicked
}
Hope this helped. Cheers!