I have a simple button that looks like:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:tag="general"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#343535"
android:orientation="vertical"
tools:context=".fragments.GeneralFragment">
<Button
android:id="#+id/hello"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:onClick="onClick"
android:text="#string/hello" />
Instead of static, these buttons should now be dynamic
Button button = (Button) layout.getChildAt(0);
for(String text : readFromSharedPreferences) {
// Set the layout
Button btn = new Button(this.getContext());
btn.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
btn.setText(text);
btn.setTag(text);
btn.setLayoutParams(button.getLayoutParams());
btn.setBackground(button.getBackground());
layout.addView(btn);
The static button has an animation when I click on it. That looks like this:
But the dynamic button has no animation. So when I click on it, nothing happens. That looks like this:
How can I add this animation to my dynamic buttons?
Update
I have figured out that my loop contains an on-touch listener. That looks like this:
btn.setOnTouchListener(new OnSwipeTouchListener(getContext()) {
// No code in here
});
If I remove that listener (even if it contains no code), the animation works great but I would like to keep it, because of my swipe function that is placed into it.
That is my whole code:
// Swiping to link
btn.setOnTouchListener(new OnSwipeTouchListener(getContext()) {
#Override
public void onSwipeLeft() {
super.onSwipeLeft();
// Alert to ask
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Delete");
builder.setMessage("Do you want to delete?");
// Delete
builder.setPositiveButton("Yes", (dialog, which) -> {
// Set the SharedPreferences as String
ArrayList<String> currentSharedPreferences = readFromSharedPreferences(getContext());
currentSharedPreferences.remove(btn.getTag().toString());
Gson gson = new Gson();
String currentSharedPreferencesAsText = gson.toJson(currentSharedPreferences);
// Update the SharedPreference k-text
SharedPreferences mPrefs = getContext().getSharedPreferences("k-texts", Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = mPrefs.edit();
prefsEditor.putString("k-text", currentSharedPreferencesAsText);
prefsEditor.apply();
// Start the animation
btn.animate()
.translationX(-btn.getWidth())
.alpha(0.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
btn.clearAnimation();
btn.setVisibility(View.GONE);
Snackbar.make(view, "Entry deleted.", Snackbar.LENGTH_LONG).setAction("Delete", null).show();
}
});
});
// Cancel
builder.setNegativeButton("No", (dialog, which) -> {
// Silence is golden
});
builder.show();
}
#Override
public void onClick() {
MainActivity mainActivity = new MainActivity();
Tts tts = new Tts(getContext(), _mediaPlayer, mainActivity.barTop, mainActivity.barBottom);
try {
tts.say(btn.getTag().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
});
Well I could use
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
Then the animation will work but onClick() wouldn't work anymore.
Another update
I had a similar problem on another view. There my static button was not having a click effect. Then I have just simply added android:foreground="?attr/selectableItemBackground" and it worked! The same way I have just tried with my dynamic button. So I have added btn.setForeground(button.getForeground()); but that doesn't do anything.
Use MaterialButton instead of Button. MaterialButton is a subtype of Button that supports additional features. The Button that is in your XML layout is actually a MaterialButton if you're using a Material Components theme. The theme automatically swaps out Buttons for MaterialButtons when your XML is inflated. So, when dynamically creating buttons in your Java code, you must use MaterialButton if you want it to match the original.
Also, when using MaterialButton, never call setBackground() because this causes undefined behavior. It likely will prevent the ripple effect from occurring as well.
Alternatively, you can define your Button in its own XML file, even with the layout params it needs for LinearLayout. Then inflate the XML each time you need another button.
for(String text : readFromSharedPreferences) {
Button btn = requireContext().getLayoutInflater()
.inflate(R.layout.my_button, layout, true); // true adds it to layout
btn.setText(text);
btn.setTag(text);
}
Related
I'm new to Android developing and now I'm trying to simulate click on my AutoCompleteTextView object.
I'm expecting default android's keyboard appearance with the possibility to type something at the element
Here is a simple function, where I'm trying to perform it:
private void someTestMethodName() {
AutoCompleteTextView tagSearchInput = findViewById(R.id.autoCompleteTextView);
tagSearchInput.performClick();
}
And here is .xml element defining:
<AutoCompleteTextView
android:id="#+id/autoCompleteTextView"
android:text="TextView"
android:layout_width="188dp"
android:layout_height="62dp"
android:layout_alignParentStart="true"
android:layout_marginStart="108dp"
android:layout_alignParentTop="true"
android:layout_marginTop="292dp"/>
Calling performClick on a TextView does not pop up the soft keyboard, but you can quite easily do that yourself:
private void someTestMethodName() {
AutoCompleteTextView tagSearchInput = findViewById(R.id.autoCompleteTextView);
showSoftKeyboard(tagSearchInput);
}
public void showSoftKeyboard(View view){
if(view.requestFocus()){
InputMethodManager imm =(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(view,InputMethodManager.SHOW_IMPLICIT);
}
}
More information can be found here: https://github.com/codepath/android_guides/wiki/Working-with-the-Soft-Keyboard
i never used performClick, you cant use setOnClickListener to catch a click
tagSearchInput.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do somthing
}
});
I have a plain action bar menu like this:
This is what it looks like in Java:
getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
ActionBar.OnNavigationListener navigationListener = new OnNavigationListener() {
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
//when an item is selected (i.e local/My Places/etc)
return false;
}
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_spinner_dropdown_item, new String[] { "Local", "My Places", "Checkins", "Latitude" });
getActionBar().setListNavigationCallbacks(adapter, navigationListener);
The callback for when an item is selected works fine, but I want a callback for when the dropdown is opened/closed.
I've looked at ActionBar.OnMenuVisibilityListener but the following prints nothing in my console.
ActionBar.OnMenuVisibilityListener listener = new ActionBar.OnMenuVisibilityListener() {
#Override
public void onMenuVisibilityChanged(boolean isVisible) {
System.out.println("hello world!");
};
};
getActionBar().addOnMenuVisibilityListener(listener);
What can I try next?
Recently I face the same task. And I use the same method to show Spinner.
But to solve this I have to replace this Spinner with custom one. I remove this code and put own Spinner through xml layout of my activity.
<com.company.yourapp.View.MenuSpinner
android:id="#+id/catalogue_menu_spinner"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentLeft="true"
android:layout_below="#id/catalogue_status_bar"
android:background="#null"
android:layout_marginLeft="60dp" />
Class that notify me when menu is showed (MenuSpinner in code above) I get from this question.
I hope my answer will help someone who like me stuck on this.
I have an android app that uses some custom dialogs which are inflated from XML layouts. The contents of the dialog's view come from the XML layout, but the actual positive and negative buttons are added by calling the builder's setPositiveButton and setNegativeButton methods, so I have no control over (or at least don't know how to control) the styling of the buttons themselves.
See the onCreateDialog method below from my LoginConfirmationDialog.java file which extends DialogFragment. It basically pops a very simple dialog up that asks for confirmation of who is logging in (i.e. "Are you Joe Schmoe?", with Yes and No buttons).
The XML layout in this case has just a single TextView, and to make this easy (because the users will be construction workers with big knobby dirty fingers who need large text and large buttons), I made the font for the TextView pretty big. The two buttons though have much smaller font for their text, and since they aren't part of my layout and are added with the setPositiveButton and setNegativeButton methods, how do I control the font size?
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = this.getArguments();
String empName = args.getString("empName");
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_login_confirmation, null);
TextView message = (TextView)view.findViewById(R.id.txtLoginConfirmationMessage);
message.setText("Are you " + empName + "?");
builder.setView(view);
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mListener.onEmpConfirmPositiveClick(LoginConfirmationDialog.this);
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mListener.onEmpConfirmNegativeClick(LoginConfirmationDialog.this);
}
});
// Create the AlertDialog object and return it
return builder.create();
}
Instead of returning builder.create(), try this.-
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
Button btnPositive = alert.getButton(Dialog.BUTTON_POSITIVE);
btnPositive.setTextSize(TEXT_SIZE);
Button btnNegative = alert.getButton(Dialog.BUTTON_NEGATIVE);
btnNegative.setTextSize(TEXT_SIZE);
}
});
return alert;
Took me a while, to integrate Asok's answer, since I used anonymous inner classes for buttons, so I needed to get a handle on the button references. This works. Make sure it goes after the messageDialog.show() line:
messageDialog.show();
messageDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextSize(TypedValue.COMPLEX_UNIT_SP, 25.0f);
messageDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setTextSize(TypedValue.COMPLEX_UNIT_SP, 25.0f);
Note: It's recommended to use sp as a unit for text size. Unlike px, it is device density independent.
You can try this:
AlertDialog.Builder builder = new AlertDialog.Builder(CompQuestionsActivity.this);
builder.setMessage("Message");
builder.setPositiveButton("Yes", dialogClickListener);
builder.setNegativeButton("No", dialogClickListener);
AlertDialog alertDialog = builder.create();
alertDialog.show();
//For positive button:
Button button1 = alertDialog.findViewById(android.R.id.button1);
button1.setTextSize(25);
//For negative button:
Button button2 = alertDialog.findViewById(android.R.id.button2);
button2.setTextSize(25);
Since you are already using an xml file for the dialog why not just include the two buttons in the layout and set the onClick handlers in the dialog creation, something like this should work. I am using something similar.
Here is a quick example:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_login_confirmation, null);
TextView message = (TextView)view.findViewById(R.id.txtLoginConfirmationMessage);
message.setText("Are you " + empName + "?");
Button positiveBtn = (Button) view.findViewById(R.id.dialogButtonPositive);
// Set size of button in relation to screen size
positiveBtn.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) 25);
positiveBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mListener.onEmpConfirmPositiveClick(LoginConfirmationDialog.this);
}
});
Button negativeBtn = (Button) view.findViewById(R.id.dialogButtonNeg);
// Set size of button in relation to screen size
negativeBtn.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) 25);
negativeBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mListener.onEmpConfirmNegativeClick(LoginConfirmationDialog.this);
}
});
builder.setView(view);
return builder.create();
I am also quite fond of using the following for setting text sizes, this allows for various screen sizes to get a different size of text (You can play with the float value to suit your needs):
.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) 25);
You should check out the following answer:
In Dialog.java (Android src) a ContextThemeWrapper is used. So you could copy the idea and do something
You just have to change the following line of code:
<item name="android:textSize">10sp</item> to your desired size.
And don't forget to check the comments of the answer also.
Best of luck.
I have tried many devices using setOnShowListener . But it did not work for all devices. In the end I come to a decision that the most easiest way is to using a Theme for your alertDialog.
Add this to the style file.
<style name="MyAlertDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:textSize">10sp</item>
</style>
Now Use this in your AlertDialog
val dialog = AlertDialog.Builder(requireActivity(),R.style.MyAlertDialogTheme)
Thats all.
My approach is to obtain the buttons in onResume() and configure them there
public class LoginConfirmationDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// your code here remains unchanged
}
#Override
public void onResume() {
super.onResume();
Button positiveButton = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
Button negativeButton = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEGATIVE);
negativeButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
}
Could someone suggest a way to change font in a dynamically created AlertDialog (in title and body)? I tried in loads of ways, but none of them worked. The code is:
public void onClick(View v) {
new AlertDialog.Builder( c )
.setTitle( data.eqselect )
// .set
.setIcon(R.drawable.icon)
.setMessage(Threads.myData[0] )
.setNegativeButton( "Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d( "AlertDialog", "Negative" );
}
} )
.show();
}
Instead of setting the text of the alertdialog, you should set a custom view form your layouts. And before you do so, modify your view's font.
TextView mycontent = (TextView) findViewById(R.id.yourid);
mycontent.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf")
And to set the view of your alert dialog, call .setView(mycontent) instead of setMessage()
Although this doesn't change your title as far as I know.
Update
I'm seeing you're unable to get what I'm saying, so here's a full example
TextView content = new TextView(this);
content.setText("on another font");
content.setTypeface(Typeface.SANS_SERIF);
//Use the first example, if your using a xml generated view
AlertDialog.Builder myalert = new AlertDialog.Builder(this);
myalert.setTitle("Your title");
myalert.setView(content);
myalert.setNeutralButton("Close dialog", null);
myalert.setCancelable(true);
myalert.show();
This is using a TextView that we've just created, and it won't have margins or such. If you use a readily created one form your layout files, you'd be able to customize all those settings, although you can do that for this example to in code.
Of course, replace the font with the one you want..
A sample TextView from xml could be:
<TextView
android:id="#+id/yourid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="your content" />
Here is my problem. I setup the buttons exactly the way they are setup in the Android documentation, but I am getting a warning, and the button will not do anything.
Here is my Java code:
package com.variDice;
import android.app.Activity;
import android.os.Bundle;
import android.widget.*;
public class VariDiceActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//die1Clicked();
}
private void die1Clicked() {
ImageButton die1button = (ImageButton)findViewById(R.id.die1button);
die1button.setImageResource(R.drawable.icon);
}
}
...and the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1" android:layout_gravity="center_horizontal">
<ImageView
android:id="#+id/varidice_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/icon"></ImageView>
<ImageButton
android:id="#+id/die1button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#null"></ImageButton>
</LinearLayout>
...and the warning:
The method die1Clicked from the type VariDiceActivity is never used locally.
I must say that I am completely new to Android development. I made my app for the iPhone, and I am now trying to make a version for the android. The iPhone version was sooo much easier, because of the better interface builder (so I can just make an action and connect it to the button that way), so this is almost impossibly hard for me to understand. In other words, I do not understand how you connect an action to the button. Could somebody please tell me what I am doing wrong?
Try this in your xml:
<ImageButton
android:id="#+id/die1button"
android:onClick="die1Clicked"
...></ImageButton>
And in your code, change the method signature to:
public void die1Clicked(android.view.View v) {
ImageButton die1button = (ImageButton)findViewById(R.id.die1button);
die1button.setImageResource(R.drawable.icon);
}
Here is the Android Button tutorial.
To bind some behavior to an UI button, you need to register a listener that receives notifications of a certain event type. In your case, you register a OnClickListener (for the click event); just like in the following snippet:
// create the implementation of OnClickListener
private OnClickListener mDie1Listener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// get the button from layout
Button button = (Button)findViewById(R.id.die1button);
// register the onClick listener with the implementation above
button.setOnClickListener(mDie1Listener);
...
}
You need to add a click listener to your button. Put this in your onCreate():
ImageButton die1button = (ImageButton)findViewById(R.id.die1button);
die1button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// What to do when the button is clicked
});
Most answers on SO tend to use 'setOnClickListener' instead of using xml properties.
I personally prefer using xml for making items clickable in android.
The mistake you have made is setting your function as private. The function which gets called after clicking the item should be public.
There are 3 things you should keep in mind:
Define the 2 properties in xml.
android:clickable="true"
android:onClick="functionName"
Define that function in the Activity file. Make sure to keep the function public.
public void functionName(View v) {
// TODO Auto-generated method stub
}
Make sure to pass 'View v' as an argument for that function.