At first my main problem was at how to call a method from the same class, even tough I think I found a way to do this, it's not working as I expected, and I would like to know what would be the best approach to my case.
This is the code I'm working on:
public class EscolhaAtendimento extends AppCompatActivity {
private ViewPager mSlideViewPager;
private LinearLayout mDotLayout;
String TAG = "TasksSample";
private TextView[] mDots;
private SliderAdapter sliderAdapter;
Dialog myDialog;
#Override
public void onCreate (Bundle SavedInstanceState){
super.onCreate(SavedInstanceState);
setContentView(R.layout.escolha_atendimento);
mSlideViewPager = findViewById(R.id.slideViewPager);
mDotLayout = findViewById(R.id.dotsLayout);
sliderAdapter = new SliderAdapter(this);
mSlideViewPager.setAdapter(sliderAdapter);
addDotsIndicator(0);
mSlideViewPager.addOnPageChangeListener(viewListener);
myDialog = new Dialog(this);
}
public void addDotsIndicator(int position){
mDots = new TextView[8];
mDotLayout.removeAllViews();
for (int i= 0; i < mDots.length; i++){
mDots[i] = new TextView(this);
mDots[i].setText(Html.fromHtml("•"));
mDots[i].setTextSize(35);
mDots[i].setTextColor(getResources().getColor(R.color.colorTransparentWhite));
mDotLayout.addView(mDots[i]);
}
if (mDots.length > 0){
mDots[position].setTextColor(getResources().getColor(R.color.colorWhite));
}
}
ViewPager.OnPageChangeListener viewListener = new ViewPager.OnPageChangeListener(){
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected (int i) {
switch (i) {
case 0: {
myDialog.show();
}
addDotsIndicator(i);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
};
public void ShowPopup(View v) {
TextView txtclose;
//Button btnFollow;
myDialog.setContentView(R.layout.pop_upfinal);
txtclose = myDialog.findViewById(R.id.txtclose);
txtclose.setText("X");
//btnFollow = (Button) myDialog.findViewById(R.id.btnfollow);
txtclose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myDialog.dismiss();
}
});
myDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
myDialog.show();
}
}
This class is an activity that on user swipe, the text and image from the buttons will change, even though their IDs will stay the same. (That's controlled by another class, it's working well).
Now, I wanted the image button on the activity do something different depending on which page is selected, and that's why there is a initial switch on the onPageSelected method, inside the Page change listener. The image button in the layout has the android:onClick="ShowPopup" tag, and I guess that also complicates things for me, if I wanted it to do something different in that same activity? Also, calling it that way on the switch, every time I change pages, and go back to the first one the popup window will open, since my call is explicit there. (As I said, even tough I found a way to somehow call my method, or at least it's result, it's not working as I expected).
Edit
I tried then changing it like this, so that the button wouldn't rely on the android:onClick="ShowPopup" Tag, and also wouldn't need to call a void method directly on the switch:
Added
public ImageButton popupchoice;
And also this to onCreate method:
popupchoice = this.findViewById(R.id.imgslide1);
Inside the switch I called it like this to get the button ID:
popupchoice.setOnClickListener(image1);
And set the View.OnClickListener like this:
View.OnClickListener image1 = new View.OnClickListener() {
public void onClick(View v) {
TextView txtclose;
//Button btnFollow;
myDialog.setContentView(R.layout.pop_upfinal);
txtclose = myDialog.findViewById(R.id.txtclose);
txtclose.setText("X");
//btnFollow = (Button) myDialog.findViewById(R.id.btnfollow);
txtclose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myDialog.dismiss();
}
});
myDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
myDialog.show();
}
};
But that returns me:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference at .EscolhaAtendimento$1.onPageSelected(EscolhaAtendimento.java:81) Line 81 is the one inside the switch with the popupchoice.setOnClickListener(image1).
This error happens on page change, when coming back to the first Page, and also the button click won't work anymore.
I think you can use
EscolhaAtendimento.this.ShowPopup from inside your switch.
Related
I have successfully implemented a custom Dialog box that appears when the user tries to leave an activity via a back button or by using onBackPressed(). They can simply cancel the dialog box or continue, and leave the activity. This function has been implemented in multiple activities, however its making my code a lot longer than it needs to be. I wanted to know how to create a util that can be referenced in different activities, without the need for the chunk of code to copy pasted multiple times. Please note that I am retrieving the dialog title and description from string.xml
This is my code:
Dialog customDialog;
Button button_one, button_two;
TextView dialog_title, dialog_description;
customDialog = new Dialog(this);
//Back button will close app
#Override
public void onBackPressed() {
customDialog.setContentView(R.layout.custom_dialog_box);
dialog_title = customDialog.findViewById(R.id.dialog_title);
dialog_title.setText(getString(R.string.leaving_activity_warning_title));
dialog_description = customDialog.findViewById(R.id.dialog_description); dialog_description.setText(getString(R.string.leaving_activity_warning_description));
button_one = customDialog.findViewById(R.id.button_one);
button_one.setText(getString(R.string.cancel));
button_two = customDialog.findViewById(R.id.button_two);
button_two.setText(getString(R.string.leave_anyway));
button_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
button_two.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}
});
Objects.requireNonNull(customDialog.getWindow()).setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
customDialog.show();
}
UPDATE
Created a Java file called "DialogBoxMessage"
DialogBoxMessage Code:
class DialogBoxMessage {
private Dialog customDialog;
private TextView dialog_title, dialog_description;
private Button button_one, button_two;
//Custom Dialog Box Initialization
DialogBoxMessage(Button myButtonOne, TextView myDialogTitle, TextView myDialogDescription, Dialog myCustomDialog) {
customDialog = myCustomDialog;
button_one = myButtonOne;
button_two = myButtonOne;
dialog_title = myDialogTitle;
dialog_description = myDialogDescription;
}
void leaveActivity() {
customDialog.setContentView(R.layout.custom_dialog_box);
dialog_title = customDialog.findViewById(R.id.dialog_title);
dialog_title.setText(Resources.getSystem().getString(R.string.leaving_activity_warning_title));
dialog_description = customDialog.findViewById(R.id.dialog_description);
dialog_description.setText(Resources.getSystem().getString(R.string.leaving_activity_warning_description));
button_one = customDialog.findViewById(R.id.button_one);
button_one.setText(Resources.getSystem().getString(R.string.cancel));
button_two = customDialog.findViewById(R.id.button_two);
button_two.setText(Resources.getSystem().getString(R.string.leave_anyway));
button_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
button_two.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
Objects.requireNonNull(customDialog.getWindow()).setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
customDialog.show();
}
}
I input the following code in another activity
Other activity code:
//Reusable exit dialog message
DialogBoxMessage dialogBoxMessage;
//Back button will close app
#Override
public void onBackPressed() {
dialogBoxMessage.leaveActivity();
finish();
}
But it doesn't seem to work, I think there are a lot of issues... please help :(
I assume customDialog is a seperate class you wrote - therefore i would suggest you put main information like contentview, title, message or type in the constructor when you initialize ur Dialog.
For your onClick Method I suggest you create an Interface to handle Button Clicks in your
customDialog class.
This could be implemented as a static method in a utilities class. The method would require 'this' as a parameter, which contains the activity context. The method should return the result of the button press. The activity can use this response to determine if finish() should be called or not.
UPDATE
I had suggested a simple static method, but you've gone down the object-oriented route. That's fine.
However, your constructor requires passing in several views, which wouldn't appear to achieve the code efficiency you are after.
Your constructor should just require the Activity context; everything else is encapsulated in your new class.
In each Activity's onBackPressed method you will need to create the object with
dialogBoxMessage = new DialogBoxMessage(this);
before you can call any of that object's methods.
I have an activity with two buttons Next and Previous and a textview, I would like to update the textview content each time I click Next or Back
For example, If I click Next the textview should show me content from the next position or vice versa.
I think that I should be using a loop but it gives me an error when I try to do that and when I add 1 to the position (i+1) it works but it only gives me the second position, I want to get all the positions not only the second one. I don't really know if my question is clear, Hope it is :)
onBindViewHolder
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, #SuppressLint("RecyclerView") final int i) {
myViewHolder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String nextContent = listItems.get(i).getContent();
String previousContent = listItems.get(i).getContent();
Intent intent = new Intent(v.getContext(), Main2Activity.class);
intent.putExtra("next", nextContent);
intent.putExtra("prev", previousContent);
v.getContext().startActivity(intent);
}
});
}
Main2Activity
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemTextView.setText(nextContent);
}
});
btnPrev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemTextView.setText(prevContent);
}
});
It's bad practice to set click listeners in the onBindViewHolder method.
Why? Because onBindViewHolder is called each time the views are recycled for the new content to be displayed on the screen. Say you have a list of 1000 elements with 10 of them visible on the screen.
You scroll it to the end => Then onBindViewHolder would be called 990 times => 990 click listeners set.
You also want to dodge costly operations in onBindViewHolder() because your scrolling would be potentially slowed down.
More tips here:
Recyclerview(Getting item on Recyclerview)
A loop isn't the answer here, a loop is for automating something. This is an event (the user interacted) so it's not suitable.
The algorithm you probably want is basically the following:
User clicked an item
Find out the item index
Increment the index
Find the item with that index (by asking the list)
If it exists, do something with it
However, the issue in the code you posted is that your 'nextContent' is always the current item. So you need the following change (but be careful about bounds):
String nextContent = listItems.get(i+1).getContent();
String previousContent = listItems.get(i-1).getContent();
You current code isn't using a loop, so the onBind method should be called once for each value of i so it should not always be the second item
After your comments it appears you have buttons unrelated to the list, so now what you need to do is make it so every time you click an item in the RV or a Next/Prev, you store the correct index (as you have no access to i)
In the activity:
private int currentTextItem = 0;
public void setCurrentTextItem(int i) {
currentTextItem = i;
//the dots here will be how you get the text from the item
// probably recyclerView.findViewHolderForAdapterPosition(pos)
myTextView.setText( ... );
}
In your view holder code:
myViewHolder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//(You should have some kind of call back from viewholder to activity)
activity.setCurrentTextItem(i);
}
});
Then your next/prev:
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setCurrentTextItem(currentTextItem + 1);
}
});
btnPrev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setCurrentTextItem(currentTextItem - 1);
}
});
In my MainActiviy class I want to display image views of smiley faces based on the number of clicks that occur on the buttons jokes, poems and funnystories combined. However my switch statement does not seem to working as no images appear. Also if any of those image views become visible, then they should remain visible even after the user closing the app and reopening it.
I also notice a click count increasing by one when the user opens the app which is not correct. It should increase based on the buttons mentioned previously being clicked.
public class MainActivity extends AppCompatActivity {
SharedPreferencesManager prefManager = SharedPreferencesManager.getInstance(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button jokesButton = findViewById(R.id.button_jokes);
Button poemsButton = findViewById(R.id.button_poems);
Button funnyStoriesButton = findViewById(R.id.button_funny_stories);
ImageView yellowSmileyFace = findViewById(R.id.yellow_happy);
ImageView greenSmileyFace = findViewById(R.id.green_happy);
ImageView redSmileyFace = findViewById(R.id.red_happy);
jokesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
prefManager.increaseClickCount();
openContentPage("jokes");
}
});
poemsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
prefManager.increaseClickCount();
openContentPage("poems");
}
});
funnyStoriesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
prefManager.increaseClickCount();
openContentPage("funnystories");
}
});
TextView clickCountText = findViewById(R.id.click_count);
clickCountText.setText(Integer.toString(prefManager.increaseClickCount()));
switch (prefManager.increaseClickCount()){
case 4 :
yellowSmileyFace.setVisibility(View.VISIBLE);
break;
case 8 :
greenSmileyFace.setVisibility(View.VISIBLE);
break;
case 12 :
redSmileyFace.setVisibility(View.VISIBLE);
break;
default :
yellowSmileyFace.setVisibility(View.INVISIBLE);
greenSmileyFace.setVisibility(View.INVISIBLE);
redsmileyFace.setVisibility(View.INVISIBLE);
}
}
private void openContentPage(String v) {
Intent intentContentPage = new Intent(MainActivity.this, Content.class);
intentContentPage.putExtra("keyPage", v);
startActivity(intentContentPage);
}
}
below is the Shared preferences class
public class SharedPreferencesManager {
private static final String APP_PREFS = "AppPrefsFile";
private static final String NUMBER_OF_CLICKS = "numberOfClicks";
private SharedPreferences sharedPrefs;
private static SharedPreferencesManager instance;
private SharedPreferencesManager(Context context) {
sharedPrefs = context.getApplicationContext().getSharedPreferences(APP_PREFS, MODE_PRIVATE);
}
public static synchronized SharedPreferencesManager getInstance(Context context){
if(instance == null)
instance = new SharedPreferencesManager(context);
return instance;
}
public int increaseClickCount() {
int clickCount = sharedPrefs.getInt(NUMBER_OF_CLICKS, 0);
clickCount++;
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putInt(NUMBER_OF_CLICKS, clickCount);
editor.apply();
return clickCount;
}
}
You need to add a getter for your clicks
public int getClicks(){
return sharedPrefs.getInt(NUMBER_OF_CLICKS, 0);
}
Whenever you want to get your clicks currently you are calling increaseClickCount() which causes your clicks to increment before returning them. That is why it gains clicks every time you open the stage and why your switch isn't working correctly
so add the above getter to your SharedPrefrenceManager and change these two lines
switch (prefManager.increaseClickCount()){
to
switch (prefManager.getClicks()){
clickCountText.setText(Integer.toString(prefManager.increaseClickCount()));
to
clickCountText.setText(Integer.toString(prefManager.getClicks()));
Tell me if that fixes your problem
The reason for counts' increase is you use increaseClickCount() to receive click count.You have to create another method to receive current clickCount. Your switch statement works only when they equal to 4,8 or 12. Maybe you should use if instead.
I also notice a click count increasing by one when the user opens the app which is not correct
It looks to me like this line of code, in MainActivity.onCreate() method will pass a text String of count 1 to clickCountText.
clickCountText.setText(Integer.toString(prefManager.increaseClickCount()));
Also, every time you call SharedPreferencesManager.increaseClickCount, you are assigning a value to clickCount, and whatever was there gets overwritten.
int clickCount = sharedPrefs.getInt(NUMBER_OF_CLICKS, 0);
What is that value?
System.out.println is your friend.
I use this pattern
System.out.println("MyClass, MyMethod, MyVariable:" + myVariable);
I always include the class and method because it can be annoying trying to figure out where println are coming from if you leave several in for debugging purposes and want to get rid of them later.
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!
I'm running through a for-loop and am generating TextViews that should be clickable because I want to start then an intent and pass the url as parameter as well as the source.
So, I've tried this
articleURL[i].setPaintFlags(articleURL[i].getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
articleURL[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//System.out.println(articleURL[v.getId()].getText().toString());
System.out.println(v.getId());
}
});
The problem i encounter is that the v.getId() is always 0. And when i use the commented code
System.out.println(articleURL[v.getId()].getText().toString());
I get an exception that says
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
I just need the content of the TextView i clicked on. How exactly do i get it? articleURL[i] doesn't work because he doesn't know i then. How can v.getId() always be -1? No matter which one I click?
This here is the complete for-loop
TextView articleURL = new TextView[hashMapSize];
for (int i = 0; i < hashMapSize; i++) {
articleURL[i] = new TextView(getActivity());
articleURL[i].setPaintFlags(articleURL[i].getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
articleURL[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println(articleURL[v.getId()].getText().toString());
//System.out.println(v.getId());
}
});
}
You actually get the View in the parameter. Just cast it to TextView and call getText()
public void onClick(View v) {
Log.d("text",((TextView) v).getText().toString());
}
Also don't use System.out.println. This is Android, not desktop Java, and coding android is a huge difference to normal Java. You should get a book on Android and read it, otherwise your apps will start crashing pretty soon and you won't have any chance to fix them.
You may try the following:
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println(((TextView)v).getText());
}
};
// ... some loop
articleURL[i].setOnClickListener(listener);
If you also want to get index of item, try this:
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println(v.getTag());
}
};
// ... some loop
articleURL[i].setTag(i);
articleURL[i].setOnClickListener(listener);
Try this..
use this as globel
TextView articleURL[];
and then initial the articleURL like below
articleURL = new TextView[hashMapSize];
and then if your extends fragement means use below
articleURL[i] = new TextView(getActivity());
extends activity means
articleURL[i] = new TextView(this);
and
System.out.println(((TextView)v).getText().toString());