I am creating an app which uses a Toolbar like fragment at the top with a few buttons. The buttons are added programmatically.
The problem is that when I launch the app, the toolbar and buttons appear, but the buttons can't be clicked. When the buttons are moused over (I use an emulator), or clicked, they don't change at all, and don't notify my OnClickListener. However, the buttons and other components in the Fragment below it work perfectly.
The Toolbar's code:
public class ToolbarFragment extends Fragment implements
View.OnClickListener{
public static final String LOG_KEY = "SM_TOOLBAR";
public static final String TO_ADD_FEED_KEY = "TO_ADD_FEED_KEY";
public static final String TO_ADD_PROFILE_KEY = "TO_ADD_PROFILE_KEY";
public static final String TO_ADD_FRIENDS_KEY = "TO_ADD_FRIENDS_KEY";
private Button feed;
private Button profile;
private Button friends;
private Button logout;
public ToolbarFragment() {
// Required empty public constructor
}
private Button addButton(int stringID, LinearLayout linearLayout) {
Button button = new Button(getContext());
button.setText(stringID);
button.setOnClickListener(this);
linearLayout.addView(button);
return button;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
LinearLayout linearLayout = (LinearLayout)inflater.inflate(R.layout.fragment_toolbar, container, false);
Bundle arguments = getArguments();
if (arguments.getBoolean(TO_ADD_FEED_KEY)) {
Log.i(LOG_KEY, "Created feed key");
feed = addButton(R.string.feed, linearLayout);
}
if (arguments.getBoolean(TO_ADD_PROFILE_KEY)) {
Log.i(LOG_KEY, "Created profile Key");
profile = addButton(R.string.profile, linearLayout);
}
if (arguments.getBoolean(TO_ADD_FRIENDS_KEY)) {
Log.i(LOG_KEY, "Created friends key");
friends = addButton(R.string.friends, linearLayout);
}
logout = addButton(R.string.logout, linearLayout);
return linearLayout;
}
#Override
public void onClick(View view) {
Log.i(LOG_KEY, "A button was clicked.");
if (getActivity() instanceof IToolbarCallback) {
IToolbarCallback itc = (IToolbarCallback) getActivity();
if (view.equals(feed)) {
itc.feed();
}
if (view.equals(profile)) {
itc.profile();
}
if (view.equals(friends)) {
itc.friends();
}
if (view.equals(logout)) {
itc.logout();
}
}
}
}
There's no other code pertinent to this, besides the callback
interface.
public interface IToolbarCallback {
void feed();
void profile();
void logout();
void friends();
}
This is just used to let the host activity know what was clicked.
Finally, the XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="project3.csc214.project23.Fragments.Toolbar.ToolbarFragment"
android:orientation="horizontal">
I use a builder for the fragment, and here's the code:
public class ToolbarBuilder {
private boolean addFeed;
private boolean addProfile;
private boolean addFriends;
private FragmentManager fragmentManager;
private int addToID;
public ToolbarBuilder(FragmentManager fragmentManager, int addToID) {
this.fragmentManager = fragmentManager;
this.addToID = addToID;
addFeed = false;
addProfile = false;
addFriends = false;
}
public ToolbarBuilder addFeed() {
addFeed = true;
return this;
}
public ToolbarBuilder addProfile() {
addProfile = true;
return this;
}
public ToolbarBuilder addFriends() {
addFriends = true;
return this;
}
public void build() {
Bundle bundle = new Bundle();
bundle.putBoolean(ToolbarFragment.TO_ADD_FEED_KEY, addFeed);
bundle.putBoolean(ToolbarFragment.TO_ADD_FRIENDS_KEY, addFriends);
bundle.putBoolean(ToolbarFragment.TO_ADD_PROFILE_KEY, addProfile);
ToolbarFragment toolbarFragment = new ToolbarFragment();
toolbarFragment.setArguments(bundle);
fragmentManager.beginTransaction().add(addToID, toolbarFragment).commit();
}
}
Just to clarify, the buttons are receiving no inputs as far as I can tell. They aren't just failing to call onClick, they're failing to react in any way at all. As far as I know, onClick is set up correctly, the buttons are just broken on some fundamental level.
The plot has thickened. Using the exact same setups in other activities seems to make it work fine... As far as I can tell, there is were no changes.
Regardless, I decided just to hard code it for this activity so I could move on to other parts of the app. Thank you all for the consideration of the problem. I'll post again should I ever figure out what happened.
Don't compare views to see if their equal, compare ids. Here:
#Override
public void onClick(View view) {
Log.i(LOG_KEY, "A button was clicked.");
if (getActivity() instanceof IToolbarCallback) {
IToolbarCallback itc = (IToolbarCallback) getActivity();
if (view.equals(feed)) {
itc.feed();
}
if (view.equals(profile)) {
itc.profile();
}
if (view.equals(friends)) {
itc.friends();
}
if (view.equals(logout)) {
itc.logout();
}
}
}
It should be:
#Override
public void onClick(View view) {
Log.i(LOG_KEY, "A button was clicked.");
if (getActivity() instanceof IToolbarCallback) {
IToolbarCallback itc = (IToolbarCallback) getActivity();
if (view.getId() == feed.getId()) {
itc.feed();
}
if (view.getId() == profile.getId()) {
itc.profile();
}
if (view.getId() == friends.getId()) {
itc.friends();
}
if (view.getId() == logout.getId()) {
itc.logout();
}
}
}
Moreover, as you're creating the views yourself you need to also give them ids. If you're on API level 17+ you can simply call generateViewId() on the view and Android will create an unique id for you.
So do it like this:
private Button addButton(int stringID, LinearLayout linearLayout) {
Button button = new Button(getContext());
button.setText(stringID);
button.setOnClickListener(this);
linearLayout.addView(button);
button.generateViewId();
return button;
}
EDIT:
Your code seem fine, apart from what I've specified above. One thing I would try is setting the listener outside your addButton method:
private Button addButton(int stringID, LinearLayout linearLayout) {
Button button = new Button(getContext());
button.setText(stringID);
linearLayout.addView(button);
button.generateViewId();
return button;
}
if (arguments.getBoolean(TO_ADD_FEED_KEY)) {
Log.i(LOG_KEY, "Created feed key");
feed = addButton(R.string.feed, linearLayout);
feed.setOnClickListener(this);
}
if (arguments.getBoolean(TO_ADD_PROFILE_KEY)) {
Log.i(LOG_KEY, "Created profile Key");
profile = addButton(R.string.profile, linearLayout);
profile.setOnClickListener(this);
}
if (arguments.getBoolean(TO_ADD_FRIENDS_KEY)) {
Log.i(LOG_KEY, "Created friends key");
friends = addButton(R.string.friends, linearLayout);
friends.setOnClickListener(this);
}
logout = addButton(R.string.logout, linearLayout);
logout.setOnClickListener(this);
If that doesn't work, try to check if there isn't any other view on top of your buttons that's intercepting the click events.
This is probably because your Activity host haven't implementing the IToolbarCallback. You need to check for it with something like this:
#Override
public void onClick(View view) {
Log.i(LOG_KEY, "A button was clicked.");
if (getActivity() instanceof IToolbarCallback) {
Log.i(LOG_KEY, "IToolbarCallback is implemented.");
} else {
Log.e(LOG_KEY, "No IToolbarCallback implemented!!!");
}
}
The problem is you did not set any id to button. So in that case all buttons have same id. You have to set a unique id explicitly to each button .
private Button addButton(int stringID,int id, LinearLayout linearLayout) {
Button button = new Button(this);
button.setText(stringID);
button.setId(id);
button.setOnClickListener(this);
linearLayout.addView(button);
return button;
}
Then add a Id to each button . Keep that in mind that id should be unique and it must be a positive int. Or you can use view.generateViewId(); directly.
feed = addButton(R.string.feed,1, linearLayout);
profile = addButton(R.string.profile,2, linearLayout);
friends = addButton(R.string.friends,3, linearLayout);
logout = addButton(R.string.logout, 4,linearLayout);
Then modify your onClick() as follows
#Override
public void onClick(View v) {
switch (v.getId()) {
case feed.getId():
itc.feed();
break;
case profile.getId():
itc.profile();
break;
case friends.getId():
itc.friends();
break;
case logout.getId():
itc.logout();
break;
default:
break;
}
}
Related
I am new to android studio and Java. I have create custom dialog box with input textbox. I want to pass data from custom dialog to fragment layout. How can I achieve that ?
I saw this post but didn't get it. Please help me out !
Passing a data from Dialog to Fragment in android
Edited
Here's my code >>
public class IncomeFragment extends Fragment{
TextView title, textRsTotal;
Dialog dialog;
int total = 0;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
title = view.findViewById(R.id.totalIncomeTitle);
Button button = view.findViewById(R.id.addIncomeBtn);
textRsTotal = view.findViewById(R.id.totalExpenseTitle);
dialog = new Dialog(getActivity());
if (getActivity() != null) {
if (!CheckInternet.isNetworkAvailable(getActivity())) {
//show no internet connection !
}
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.setContentView(R.layout.income_custom_dialog);
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
RadioGroup radioGroup = dialog.findViewById(R.id.radioGroup);
Button buttonAdd = dialog.findViewById(R.id.addBtn);
TextInputEditText editText = dialog.findViewById(R.id.editText);
radioGroup.clearCheck();
radioGroup.animate();
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
RadioButton radioButton = (RadioButton) radioGroup.findViewById(checkedId);
}
});
buttonAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int selectedId = radioGroup.getCheckedRadioButtonId();
if (selectedId == -1) {
Toast.makeText(getActivity(), "Please select your income type", Toast.LENGTH_SHORT).show();
} else {
RadioButton radioButton = (RadioButton) radioGroup.findViewById(selectedId);
String getIncome = editText.getText().toString();
Toast.makeText(getActivity(), radioButton.getText() + " is selected & total is Rs."+ total, Toast.LENGTH_SHORT).show();
}
}
});
dialog.show();
}
});
super.onViewCreated(view, savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_income, container, false);
// Inflate the layout for this fragment
return view;
}
}
Ok, try this :
public class IncomeFragment extends Fragment {
TextView title, textRsTotal;
Dialog dialog;
int total = 0;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
title = view.findViewById(R.id.totalIncomeTitle);
Button button = view.findViewById(R.id.addIncomeBtn);
textRsTotal = view.findViewById(R.id.totalExpenseTitle);
dialog = new Dialog(getActivity());
if (getActivity() != null) {
if (!CheckInternet.isNetworkAvailable(getActivity())) {
//show no internet connection !
}
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog(new MyCallback() {
#Override
public void setText(String text) {
textRsTotal.setText(text);
}
});
}
});
super.onViewCreated(view, savedInstanceState);
}
private void showDialog(MyCallback myCallback) {
dialog.setContentView(R.layout.income_custom_dialog);
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
RadioGroup radioGroup = dialog.findViewById(R.id.radioGroup);
Button buttonAdd = dialog.findViewById(R.id.addBtn);
TextInputEditText editText = dialog.findViewById(R.id.editText);
radioGroup.clearCheck();
radioGroup.animate();
radioGroup.setOnCheckedChangeListener((radioGroup1, checkedId) -> {
RadioButton radioButton = (RadioButton) radioGroup1.findViewById(checkedId);
});
buttonAdd.setOnClickListener(view1 -> {
int selectedId = radioGroup.getCheckedRadioButtonId();
if (selectedId == -1) {
Toast.makeText(getActivity(), "Please select your income type", Toast.LENGTH_SHORT).show();
} else {
RadioButton radioButton = (RadioButton) radioGroup.findViewById(selectedId);
String getIncome = editText.getText().toString();
myCallback.setText(getIncome);
Toast.makeText(getActivity(), radioButton.getText() + " is selected & total is Rs." + total, Toast.LENGTH_SHORT).show();
}
});
dialog.show();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_income, container, false);
return view;
}
public interface MyCallback {
void setText(String text);
}
}
There are more than one method to achieve that, the one mentioned in the url you provided is suggesting to use a simple callback to forward event and data back to the calling fragment. So the pieces you are needing are all there:
Write a callback interface: public interface Callback1{ public void onInteraction(String thingToCommunicateBack); }
In your fragment: and while building the instance of your dialog, pass an instance you've built of Callback1 to that dialog like this Callback1 mCallback = new Callback1() { public void onInteraction(String thingToCommunicateBack) { /*TODO receive data, handle and update layout*/ }; (the whole fragment could be that instance using the keyword this if you decide to implement the interface there instead, like this
class Fragment1 extends Fragment implements Callback1 and implement its method within fragment's class after the keyword override)
In your Dialog class: when the interaction (click) that should trigger the event and send data back happens, invoke callback's method like this: mCallback1.onInteraction("text from your EditText to pass")
Now, you passed some data from custom dialog back to a fragment.
I have a problem with passing data in android. let me explain my problem.
there are two activities called MainActivity and ProductInformationActivity.
in mainActivity there is a settingButton and onClickListener of the button, a bottom sheet dialog will open up. in bottomSheetDialog there are saveButton and three editText. whenever a user click on saveButton it should pass editTexts data's as PercentageClass to productInformationActivity . (percentage Class is a model to save percentages and pass theme between activities).
I create an interface Called "OnPercentageClicked" then I created an instance of this interface and create setter for that (setOnAddPercentageClicked).
in saveButtonListener I create instance of percentege class and set EditTexts data to it and finally I add percentage to interface's method.
this is mainACtivity:
public class MainActivity extends AppCompatActivity {
private View bottomSheetView;
private BottomSheetDialog bottomSheetDialog;
private OnAddPercentageClicked onAddPercentageClicked;
public void setOnAddPercentageClicked(OnAddPercentageClicked onAddPercentageClicked) {
this.onAddPercentageClicked = onAddPercentageClicked;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar mainToolbar = findViewById(R.id.mainToolbar);
setSupportActionBar(mainToolbar);
ImageButton settingbtn = findViewById(R.id.activityMain_settingBTN);
ViewPager2 viewPager2 = findViewById(R.id.activityMain_viewpager);
TabLayout tabLayout = findViewById(R.id.activityMain_tabLayout);
MainViewPagerAdapter adapter = new MainViewPagerAdapter(this);
viewPager2.setAdapter(adapter);
createDialog();
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
switch (position){
case 0 : tab.setText("کالا ها"); break;
case 1 : tab.setText("دسته بندی ها"); break;
}
}
});
tabLayoutMediator.attach();
settingbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bottomSheetDialog.show();
TextInputEditText firstPercentage = bottomSheetDialog.findViewById(R.id.priceIncrementPercentage_firstPercentageET);
TextInputEditText secondPercentage = bottomSheetDialog.findViewById(R.id.priceIncrementPercentage_secondPercentageET);
TextInputEditText thirdPercentage = bottomSheetDialog.findViewById(R.id.priceIncrementPercentage_thirdPercentageET);
Button percentageSaveButton = bottomSheetDialog.findViewById(R.id.priceIncrementPercentage_saveBTN);
assert percentageSaveButton != null;
percentageSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (firstPercentage.getText().length()>0 && secondPercentage.getText().length()>0 && thirdPercentage.getText().length()>0){
Percentage percentage = new Percentage();
percentage.setFirstPercentage(Integer.parseInt(firstPercentage.getText().toString()));
percentage.setSecondPercentage(Integer.parseInt(secondPercentage.getText().toString()));
percentage.setThirdPercentage(Integer.parseInt(thirdPercentage.getText().toString()));
onAddPercentageClicked.onButtonClicked(percentage);
bottomSheetDialog.dismiss();
Toast.makeText(MainActivity.this, "ذخیره شد", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "لطفا همه ی فیلد ها را پر کنید", Toast.LENGTH_SHORT).show();
}
}
});
}
});
}
public void createDialog(){
bottomSheetDialog = new BottomSheetDialog(MainActivity.this,R.style.bottom_sheet_dialog_theme);
bottomSheetDialog.setContentView(getLayoutInflater().inflate(R.layout.price_increment_percentage,(LinearLayout)findViewById(R.id.priceIncrementPercentage_container),false));
}
}
in productInfomation Activity i want to get the percentage class which i used in MainActivity.
so I implement OnAddPercentageClicked then I create an instance of main activity and call the setter which I created in MainActivity (setOnAddPercentageClicked).
this is productInformationActivity :
public class ProductInformation extends AppCompatActivity implements View.OnClickListener ,OnAddPercentageClicked{
private Percentage percentage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_information);
MainActivity mainActivity = new MainActivity();
mainActivity.setOnAddPercentageClicked(this);
TextView productName = findViewById(R.id.activityProductInformation_productNameTV);
TextView productPrice = findViewById(R.id.activityProductInformation_productPriceTV);
TextView productPriceFirstPercentage = findViewById(R.id.productPriceFirstPercentage);
TextView productPriceSecondPercentage = findViewById(R.id.productPriceSecondPercentage);
TextView productPriceThirdPercentage = findViewById(R.id.productPriceThirdPercentage);
TextView productCategoryName = findViewById(R.id.activityProductInformation_categoryNameTV);
ImageButton close = findViewById(R.id.activity_product_information_closeIB);
close.setOnClickListener(this);
if (percentage !=null){
productPriceFirstPercentage.setText("قیمت کالا +"+percentage.getFirstPercentage()+" درصد");
productPriceSecondPercentage.setText("قیمت کالا +"+percentage.getSecondPercentage()+" درصد");
productPriceThirdPercentage.setText("قیمت کالا +"+percentage.getThirdPercentage()+" درصد");
}
//
// }
if (getIntent().hasExtra("PRODUCT")){
Product product = getIntent().getParcelableExtra("PRODUCT");
productName.setText(product.getTitle());
productPrice.setText(String.valueOf(product.getPrice()));
productCategoryName.setText(String.valueOf(product.getCategoryId()));
}
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.activity_product_information_closeIB){
finish();
}
}
#Override
public void onButtonClicked(Percentage percentage) {
Log.i(TAG, "onButtonClicked: " + percentage);
this.percentage = percentage;
}
}
and when i run this code i get an error which says that the interface in MainActicvity is null.
would you please help me ?
thanks.
I have a save menu option in my fragment where I save the user's data, I also want to save the data onbackpressed in fragments?How can I achieve this ?
This is my saveMethod:
public void saveNote() {
title = edit_title.getText().toString().trim();
text = txtnote2.getText().toString().trim();
if (title.isEmpty()) {
Toast.makeText(getActivity(), "Please enter a title", Toast.LENGTH_SHORT).show();
}
else if (!text.isEmpty() || !title.isEmpty()) {
long date = new Date().getTime(); // get current time;
if (temp == null) {
temp = new Note(title, text, date,activityName);
dao.insertNote(temp); //inserts note record to db;
} else {
temp.setNoteTitle(title);
temp.setNoteText(text);
temp.setNoteDate(date);
temp.setActivityName(activityName);
dao.updateNote(temp);
}
Toast.makeText(getActivity(), "Saved!!", Toast.LENGTH_SHORT).show();
// finish(); //return to main activity
getActivity().startActivity(new Intent(getActivity(),MainActivity.class));
getActivity().finish();
}
}
I want to call this method onbackpressed in fragments
How can this be done ?
To tell fragments when the back button has been pressed, first of all you need a base fragment which all of your other fragments inherit from. This base fragment implements the following:
public interface OnBackPressed {
void onBackPressed();
}
public class BaseFragment extends Fragment implements OnBackPressed {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onBackPressed() {
// do what you want to save
saveNote()}
}
Now in your hosting Activity, call any implementations of the interface before any fragments are popped:
#Override
public void onBackPressed() {
saveData()
super.onBackPressed();
}
private void saveData(){
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f : fragments){
if(f != null && f instanceof BaseFragment)
((BaseFragment)f).onBackPressed();
}
}
Have you tried this:
public class BaseFragment extends Fragment {
/**
* Could handle back press.
* #return true if back press was handled
*/
public boolean onBackPressed() {
return false;
}
}
Background info:
I am required to create an SOS game. I decided to implement a grid view with a 7x7 grid of SOSButtons (Button extending AppCompatButton).
Problem:
After calling setOnClickListener() within my SOSButton class, I expect to see an onClickListener of some sort to be attached to my button, however there is none.
When running the application, it has no issue, and displays perfectly. When clicking on any button within the grid, no listener is fired.
When clicking any other button outside of the grid, it fires as expected.
Note: I see this by setting a breakpoint after the setOnClickListener() line, and view the SOSButton object "mListeners = null"
Note 2: I attempted to remove all unnecessaries and use a simple Button object, with an onClickListener() as shown below, but with no avail:
Button button = new Button(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "click occured from main avtivity delcaration", Toast.LENGTH_SHORT).show();
Button b = (Button) view;
String s = b.getText().toString();
switch (s){
case "S" : {
b.setText("O");
break;
}
case "O" : {
b.setText("");
break;
}
case "" : {
b.setText("S");
break;
}
}
}
});
list.add(button);
I tried:
SOSButton with onClickListener set in Button constructor
SOSButton with onClickListener set in Button constructor and GridView.setOnItemClickListener
SOSButton with only GridView.setOnItemClickListener
Button with onClickListener set in Button constructor
Button with onClickListener set in Button constructor and GridView.setOnItemClickListener
Button with only GridView.setOnItemClickListener
None of the above fired any listener. The only listeners firing were those of buttons NOT in the gridview.
More Info:
SOSButton.java
package wrap302.nmu.task1_sos;
import android.content.Context;
import android.support.v7.widget.AppCompatButton;
import android.view.View;
public class SOSButton extends AppCompatButton {
private SO_Select so_select;
public SOSButton(Context context) {
super(context);
so_select = SO_Select.None;
OnClickListener onClickListener = new OnClickListener() {
#Override
public void onClick(View view) {
switch (so_select) {
case None: {
so_select = SO_Select.S;
break;
}
case S: {
so_select = SO_Select.O;
break;
}
case O: {
so_select = SO_Select.None;
break;
}
}
SOSButton.this.update();
}
};
setOnClickListener(onClickListener);
update();
}
private void update(){
setText(so_select.toString());
}
#Override
public String toString() {
return "SOSButton{" +
"so_select=" + so_select.toString() +
'}';
}
}
SO_Select enum:
package wrap302.nmu.task1_sos;
public enum SO_Select {
None(""),
S("S"),
O("O");
private String state;
SO_Select(String state) {
this.state = state;
}
#Override
public String toString() {
return state;
}
}
SOSButtonMatch interface:
package wrap302.nmu.task1_sos;
import android.widget.Button;
interface SOSButtonMatch {
/**
* Interface to check 3 buttons' text and return true if text follows a sequence specified
*
* #param b1 Start button
* #param b2 Middle button
* #param b3 End button
* #return Boolean
*/
boolean check(Button b1, Button b2, Button b3);
}
SOS_Adapter for the grid:
package wrap302.nmu.task1_sos;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import java.util.List;
public class SOS_Adapter<T> extends ArrayAdapter<T>{
private int resourceId;
private Context mContext;
private List<T> items;
public SOS_Adapter(Context context, int resource, List<T> objects) {
super(context, resource, objects);
this.mContext = context;
this.items = objects;
this.resourceId = resource;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(resourceId, viewGroup, false);
v.setTag(getItem(i));
Button b = v.findViewById(R.id.sosButton);
b.setText(((SOSButton)getItem(i)).getText());
return b; //runs twice
}
}
MainActivity code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initGui();
}
/**
* Initialize gui objects
*/
private void initGui() {
btnDone = (Button) findViewById(R.id.btnDone);
btnExit = (Button) findViewById(R.id.btnExit);
btnReset = (Button) findViewById(R.id.btnReset);
grid = (GridView) findViewById(R.id.grid);
lblGridPosOpen = (TextView) findViewById(R.id.lblGridPosOpen);
lblP1_Score = (TextView) findViewById(R.id.lblP1_Score);
lblP2_Score = (TextView) findViewById(R.id.lblP2_Score);
lblPTurn = (TextView) findViewById(R.id.lblPTurn);
createAdapter();
grid.setAdapter(sos_adapter);
OnItemClickListener clickListener = new OnItemClickListener() { //runs twice
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this, "clicked", Toast.LENGTH_SHORT).show();
/*SO_Select so_select = SO_Select.None;
switch (so_select) {
case None: {
so_select = SO_Select.S;
break;
}
case S: {
so_select = SO_Select.O;
break;
}
case O: {
so_select = SO_Select.None;
break;
}
}
Object itemAtPosition = adapterView.getItemAtPosition(i);
SOSButton b = ((SOSButton) itemAtPosition);
b.setText(so_select.toString());*/
}
};
// grid.setOnItemClickListener(clickListener);
Toast.makeText(this, "displaying", Toast.LENGTH_SHORT).show();
}
private void createAdapter() {
List<SOSButton> sosButtons = generateButtons(GRID_SIZE);
sos_adapter = new SOS_Adapter(this, R.layout.sosbutton,sosButtons);
}
private List<SOSButton> generateButtons(int grid_size) {
List<SOSButton> l = new ArrayList<>();
for (int i = 0; i < grid_size; i++) {
SOSButton sosButton = new SOSButton(this);
sosButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "click occured from main avtivity delcaration", Toast.LENGTH_SHORT).show();
}
});
l.add(sosButton);
}
return l;
}
well, I found the solution after some more Googling.
Getting the button to respond to a click event whilst in the adapter is not as simple as adding a listener to the button itself.
In the SOS_Adapter, the getView() is the place to add the listener.
This is done simply by adding:
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Button b = (Button) view;
String s = b.getText().toString();
switch (s){
case "S" : {
b.setText("O");
break;
}
case "O" : {
b.setText("");
break;
}
case "" : {
b.setText("S");
break;
}
}
}
});
right before the return
Then one recieves a hard earned response to one's touch.
Could someone please explain why this needs to be done in a beat-around-the-bush way?
I am going to ask very basic question, but i am stuck in it for a long time.
after card view there is an recycleview which has 2 images in each row.
now i want to create the click listener on the images rather than the recycleview.
the corresponding layout(layout_main.xml) of this activity(MainActivity.java) contain only recyclerview. the elements of each row is in another layout(layout_images.xml). i am getting the images from layout_images.xml and inflate them in the adapter class(Adapter.java).
now how to put action listener on the images only.
secondly, i want to get the image on which i clicked. how to get that.
like, when we click on a view we create some method as
public void onClick(View view){
// some code here
}
where view is the object on which we clicked. in my case how to get the image on which i clicked.
using type cast it might be throw an exception when user doesnot click on image.
Multiple onClick events inside a recyclerView:
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public ImageView iconImageView;
public TextView iconTextView;
public MyViewHolder(final View itemView) {
super(itemView);
iconImageView = (ImageView) itemView.findViewById(R.id.myRecyclerImageView);
iconTextView = (TextView) itemView.findViewById(R.id.myRecyclerTextView);
// set click event
itemView.setOnClickListener(this);
iconTextView.setOnClickListener(this);
// set long click event
iconImageView.setOnLongClickListener(this);
}
// onClick Listener for view
#Override
public void onClick(View v) {
if (v.getId() == iconTextView.getId()) {
Toast.makeText(v.getContext(), "ITEM PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
}
}
//onLongClickListener for view
#Override
public boolean onLongClick(View v) {
final AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setTitle("Hello Dialog")
.setMessage("LONG CLICK DIALOG WINDOW FOR ICON " + String.valueOf(getAdapterPosition()))
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.create().show();
return true;
}
}
To get which item was clicked you match the view id i.e. v.getId() == yourViewItem.getId()
You have to set onClickListener to the ImageViews inside the onBindViewHolder method, refer the following LOCs for reference(code to be inside onBindViewHolder method)
holder.imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//put your code for first imageview here
}
});
holder.imageView2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//put your code for second imageView here
}
});
In Recycle View Holder, Write your onclick listener code inside
#Override
public void onBindViewHolder(CardHolder holder, final int position) {
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//TODO
}
}
}
implement the View.OnClickListener in your ViewHolder class and implement the onClick method. Then set the click listener for your ImageView to this click listener. Add the required functionality in the onClick method. If you want to implement the click functionality in other class simply create an interface and declare a click method in it. You can implement this method in the activity/fragment that contains this RecycleView. Then from your view holders onClick method you can invoke the interface method.
You can check with tag or it of element like this:
public void onClick(View view){
if(view.getId() == image1.getId())
{
}else if(view.getId() == image2.getId())
{}
}
First of all set onclickListener to each view you want to be clicked. Good place to do it in viewHolderConstructor. eg
public class GalleryManyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.im_img) RoundedCornersImageView imImg;
#BindView(R.id.tv_title) MyTextView tvTitle;
#BindView(R.id.tv_label) MyTextView tvLabel;
#BindView(R.id.tv_date) MyTextView tvDate;
#BindView(R.id.im_gallery_one) RoundedCornersImageView imGalleryOne;
#BindView(R.id.im_gallery_two) RoundedCornersImageView imGalleryTwo;
#BindView(R.id.im_gallery_three) RoundedCornersImageView imGalleryThree;
#BindView(R.id.im_gallery_four) RoundedCornersImageView imGalleryFour;
#BindView(R.id.tv_more) MyTextView tvMore;
#BindView(R.id.root) RelativeLayout root;
public GalleryManyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
view.setOnClickListener(onClickListener);
imGalleryOne.setOnClickListener(onClickListener);
imGalleryTwo.setOnClickListener(onClickListener);
imGalleryThree.setOnClickListener(onClickListener);
imGalleryFour.setOnClickListener(onClickListener);
view.setTag(this);
}
Generally you do not need to make anything specific with those view, like setting tags (Also some usefull libraries like Glied, which sets its own tags to imageviews will malfunction if you set you own tag. In on clickListener find adapter position of the view to be able to retrive the corresponding data
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override public void onClick(View v) {
View view = v;
View parent = (View) v.getParent();
while (!(parent instanceof RecyclerView)){
view=parent;
parent = (View) parent.getParent();
}
int position = recyclerView.getChildAdapterPosition(view);
}
as described here
Then but checking views id, evaluete what you want to do
switch (v.getId()) {
case R.id.im_gallery_one: {
p = 0;
}
break;
case R.id.im_gallery_two: {
p = 1;
}
break;
case R.id.im_gallery_three: {
p = 2;
}
break;
case R.id.im_gallery_four: {
p = 3;
}
break;
}