I got a custom dialog contains a checkBox. When I check the CheckBox, new view is created and added into Dialog. If I unchecked the CheckBox, it will make the view added gone and changes it back to previous view.
Here's it looks. Pictures on the left hand side is before check and left hand side is after checked.
As the dialog is checked, dialog layout will becomes bigger as pictures above.
My question is how to make dialog layout becomes bigger gradually instead of instantly.
Something like animation that make the layout expand itself gradually.
This is my work so far.
public class CreateRoomDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//Get layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
//R.layout.add_player2 is the layout shows on dialog message
view = inflater.inflate(R.layout.createroom_dialog_fragment, null);
roomName = (EditText)view.findViewById(R.id.createroom_dialog_roomname);
roomKey = (EditText)view.findViewById(R.id.createroom_dialog_key);
keyLayout = (LinearLayout)view.findViewById(R.id.keyLayout);
checkBoxLayout1 = (RelativeLayout)view.findViewById(R.id.createroom_dialog_layout1);
checkBoxLayout2 = (RelativeLayout)view.findViewById(R.id.createroom_dialog_layout2);
// lock the room with key
checkBox1 = (CheckBox)view.findViewById(R.id.createroom_dialog_checkbox1);
// show the key
checkBox2 = (CheckBox)view.findViewById(R.id.createroom_dialog_checkbox2);
checkBox1.setOnCheckedChangeListener(new CreateRoomCheckBoxListener());
checkBox2.setOnCheckedChangeListener(new CreateRoomCheckBoxListener());
}
private class CreateRoomCheckBoxListener implements OnCheckedChangeListener{
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(buttonView == checkBox1){
// lock the room with key
if(isChecked){
roomKey.setVisibility(View.VISIBLE);
checkBoxLayout2.setVisibility(View.VISIBLE);
}else{
roomKey.setVisibility(View.GONE);
checkBoxLayout2.setVisibility(View.GONE);
}
}
}
}
}
It is possible to animate a Dialog.
Please refer to this tutorial.
Sorry it is in japanese. And since I can read japanese I assume you can read japanese.
Related
I have extended EditTextPreference, but the Dialog Message won't display. This happens if I add the dialogMessage programatically or in the the preferences.xml.
Here is my onBindDialogView:
AutoCompleteTextView editText = mEditText;
editText.setText(getText());
ViewParent oldParent = editText.getParent();
if (oldParent != view) {
if (oldParent != null) {
((ViewGroup) oldParent).removeView(editText);
}
onAddEditTextToDialogView(view, editText);
}
Is the dialog message really absent? It's probably there but its text color might make it less (or not) visible. (Or try to dismiss software keyboard). Try experimenting with dialog messages having a number of "\n" characters and see if that affects dialog layout. If so, it means the dialog message is actually there but camouflaged too well.
EditTextPreference brings a text view (in the preference_dialog_edittext.xml) that replaces the existing one (in the alert_dialog.xml) for the dialog message, but unfortunately with different text style, which might cause a visibility problem under certain themes. Even their sizes are different.
One solution might be to obtain the text color and size from the original text view to be replaced and apply them to the new one, but I would suggest retaining the original text view instead, because it's more likely to be visually consistent if there are any future UI changes. Try adding the following overrides
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
builder.setMessage(getDialogMessage()); // bring back the original text view
}
protected void onAddEditTextToDialogView(View dialogView, EditText editText) {
int id = getContext().getResources().getIdentifier("edittext_container", "id", "android");
ViewGroup container = (ViewGroup) dialogView.findViewById(id);
container.removeAllViews(); // remove the new text view
super.onAddEditTextToDialogView(dialogView, editText);
}
If you think the dialog message and the edittext view is too far apart, they can be brought together a little closer by adding another override:
protected void showDialog(Bundle state) {
super.showDialog(state);
int id = getContext().getResources().getIdentifier("message", "id", "android");
TextView message = (TextView) getDialog().findViewById(id);
message.setPadding(message.getPaddingLeft(), message.getPaddingTop(), message.getPaddingRight(), 0);
}
and add the following line in the onAddEditTextToDialogView method after calling removeAllViews:
container.setPadding(container.getPaddingLeft(), 0, container.getPaddingRight(), container.getPaddingBottom());
Good day, apologies for the confusing title.
I am creating an android application and I need a dialog/pop up to appear at a specific X Y Position. I already have a working DialogFragmet as shown below:
public class ItemDialog extends DialogFragment implements OnClickListener{
//a lot of public and private variables here
public interface onSubmitListener {
void setOnSubmitListener(String qty, String disc, String instructions, UOMClass uom);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dialog = new Dialog(getActivity());
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
LayoutInflater layoutInflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout2 = layoutInflater.inflate(R.layout.fragment_item_dialog, null);
dialog.setContentView(layout2);
setStyle(DialogFragment.STYLE_NORMAL, R.style.MyDialog);
//snip snip more code
dialog.show();
//buttons - I set the buttons here
//editTexts - I set the edit texts here
//TextViews - I set the text views here
return dialog;
}
//more functions here
}
And I call it from my base activity as follows:
ItemDialog itemDialog = new ItemDialog();
//pass values from base activity to the ItemDialog here
itemDialog.show(getFragmentManager(), "");
However, I need to be able to see the base activity and input values in the edit texts in it. As of now, my DialogFragment covers a huge part of the screen and I'm unable to see the activity behind it. Clicking outside the Dialog Fragment cancels it as well.
I've searched on how to make an alert dialog float but to no avail.
Is there a way to display a Dialog Fragment over a certain area of the screen to allow the user to see and still input values in the base activity?
Any help is very much appreciated, thank you.
you can get window object and set it's layout parameters below code might help you.
Window window = getDialog().getWindow();
// set "origin" to top left corner, so to speak
window.setGravity(Gravity.TOP|Gravity.LEFT);
// after that, setting values for x and y works "naturally"
WindowManager.LayoutParams params = window.getAttributes();
params.x = 300;
params.y = 100;
window.setAttributes(params);
for more info Position of DialogFragment in Android
you can also set background color or bitmap to dialog
Here is what I am aiming for:
I am unsure if I am doing this correctly. There are probably better,more efficient, and cleaner ways to do it, but I need to know how.
This layout was designed in xml and inflated via an inflater. The produced view was then placed into an AlertDialog. Thus, this is seen as an AlertDialog by the user.
My concern is with the tags section at the bottom. I want this to work like how Tumblr tags work. Type a string, hit the button, and a button with that tag name will show up in the blank section below it.
Now, if you click on those buttons (with their respective tag names), they will disappear from the frame.
I have several concerns.
I have trouble implementing listeners. If the AddTag button creates more buttons in the (currently invisible, but present) LinearLayout, then what about the created buttons? How do those buttons implement onClick listeners that will remove themselves from the LinearLayout if they were created in some inner method defined from the AddTag button's onClick method?
I am afraid about having to declare some of these views as FINAL in order to reference them in button methods and inner classes. I am now stuck because of this.
Do I have to define my own layout for the tag buttons? You see, a LinearLayout displays things one after the other, yes? I want to try to recreate how some social networking sites do it. Fill the layout with buttons from top to bottom, left to right. If there is no room left in the current row, go to the next one and add the tag button there. It's basically a dynamic LinearLayout that has autowrapping.
If there are any better ways of implementing this, please let me know a general step by step of what to do. I have not learned Fragments yet, but I think it may be VERY applicable here. Also, should I be creating a class that extends ViewGroup, inflating the XML there, and adding helper methods to handle things? I suppose from a DialogFragment I could then addView(the class I just created) and work from there?
Here is my current code by the way. I am stuck and stumped.
/**
* Opens a view for the user to define their new action and add it to the
* dictionary.
*
* #param view
*/
public void defineNewAction(View view) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
View viewToSet = inflater.inflate(
R.layout.define_new_action_window_layout,
null);
final EditText newActionName = (EditText) viewToSet
.findViewById(R.id.set_action_name);
final RadioGroup priorityGroup = (RadioGroup) viewToSet
.findViewById(R.id.radiogroup_set_priority);
final EditText goalTimeHours = (EditText) viewToSet
.findViewById(R.id.set_goal_time_hours);
final EditText goalTimeMinutes = (EditText) viewToSet
.findViewById(R.id.set_goal_time_minutes);
final EditText addTagsInput = (EditText) viewToSet
.findViewById(R.id.add_tags_input);
Button addTagButton = (Button) viewToSet.findViewById(R.id.btn_add_tags);
final ArrayList<String> tags = new ArrayList<String>();
final LinearLayout currentTagsLayout = (LinearLayout) viewToSet
.findViewById(R.id.current_tags);
addTagButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String tag = addTagsInput.getText().toString();
tags.add(tag);
Button newTag = new Button(builder.getContext());
int tagId = tag.hashCode();
if (tagId < 0)
tagId *= -1;
newTag.setId(tagId);
newTag.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Button toRemove = (Button) currentTagsLayout.findViewById(tagId);
currentTagsLayout.removeView(toRemove);
}
});
currentTagsLayout.addView(newTag);
}
});
builder.setTitle("Define your action.");
builder.setView(viewToSet);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
String name = newActionName.getText().toString();
int priority = priorityGroup.getCheckedRadioButtonId();
int goalHours = Integer
.parseInt(goalTimeHours.getText().toString());
int goalMinutes = Integer.parseInt(goalTimeMinutes.getText()
.toString());
}
});
builder.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
I have trouble implementing listeners
There's no trouble. For the functionality you are trying to achieve, you can keep adding buttons and setting OnClickListeners on them. You don't even need to give them an id, or track them in any way. The following code inside your OnClickListener will do:
newTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Use the View given to you
currentTagsLayout.removeView(v);
}
});
I am afraid about having to declare some of these views as FINAL
This is how Java works. I haven't noticed any crippling effects of this. You can also declare your variables as global to not have to define them as final. But I don't see why declaring them as final is an issue. Could you provide an example where this is a problem?
Do I have to define my own layout for the tag buttons?
This is something you will have to deal with yourself. It's a design decision. If you need auto-wrapping support, you can look at Android Flow Layout: Link. It's an extended LinearLayout that supports auto-wrap of its contents.
I have not learned Fragments yet, but I think it may be VERY
applicable here
I don't see why they would be.
Note/Aside: Some kind of a check here would be better:
String tag = "";
if (!addTagsInput.getText().toString().equals("")) {
tag = addTagsInput.getText().toString();
} else {
// handle empty string
}
I have an AlertDialog with just some text, a NumberPicker, an OK, and a Cancel.
package org.dyndns.schep.example;
import android.os.Bundler;
import android.view.View;
import android.widget.NumberPicker;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
public class FooFragment extends DialogFragment {
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mParent = (MainActivity) activity;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
mParent.setFoo(foo());
}
})
.setNegativeButton(android.R.string.cancel, null);
View view = getActivity().getLayoutInflater.inflate(
R.layout.dialog_foo, null);
mPicker = (NumberPicker) view.findViewById(R.id.numberPicker1);
mPicker.setValue(mParent.getFoo());
builder.setView(view);
return builder.create();
}
public int foo() {
return mPicker.getValue();
}
private MainActivity mParent;
private NumberPicker mPicker;
}
(This dialog doesn't yet do the things it should to preserve state on Pause and Resume, I know.)
I would like the "Done" action on the soft keyboard or other IME to dismiss the dialog as though "OK" were pressed, since there's only the one widget to edit.
It looks like the best way to deal with an IME "Done" is usually to setOnEditorActionListener on a TextView. But I don't have any TextView variable, and NumberPicker doesn't obviously expose any TextView, or similar editor callbacks. (Maybe NumberPicker contains a TextView with a constant ID I could search for using findViewById?)
NumberPicker.setOnValueChangedListener does get triggered on the "Done" action, but it also fires when tapping or flicking the list of numbers, which definitely should not dismiss the dialog.
Based on this question, I tried checking out setOnKeyListener, but that interface didn't trigger at all when using the soft keyboard. Not a total surprise, since the KeyEvent documentation suggests it's meant more for hardware events, and in recent APIs the soft keyboard won't send them at all.
How can I connect the IME "Done" to my dialog's "OK" action?
Edit: From the looks of the source, a NumberPicker layout does contain a EditText, but its id is id/numberpicker_input in package com.android.internal. Using that would not be easy, and is obviously discouraged. But it seems like there might only be hack ways to get the behavior I want.
How can I connect the IME "Done" to my dialog's "OK" action?
The problem is that you can't pass the IME's events if you don't have a listener set on the TextView widget which currently works with the IME. One way to do what you want is to hook our own logic to the NumberPicker's child which works with the IME(like you already talked in the last part of your question). To avoid using certain ids or other layout tricks(which can be problematic) to get a hold of that widget, you could use a greedy tactic, setting the listener to any widget from the NumberPicker which could trigger the desired event(TextViews or any subclass of TextView). Something like this:
private AlertDialog mCurrentDialog;
private List<TextView> mTargets = new ArrayList<TextView>();
private OnEditorActionListener mListener = new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// if a child of NumberPicker triggers the DONE editor event
// get a reference to the positive button(which you use in your
// code) and click it
mCurrentDialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
}
return false;
}
};
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// ...
mPicker = (NumberPicker) view.findViewById(R.id.numberPicker1);
mPicker.setValue(mParent.getFoo());
// clear any previous targets
mTargets.clear();
// find possible targets in the NumberPicker
findTextViews(mPicker);
// setup those possible targets with our own logic
setupEditorListener();
builder.setView(view);
// get a reference to the current showed dialog
mCurrentDialog = builder.create();
return mCurrentDialog;
}
Where the methods are:
private void findTextViews(ViewGroup parent) {
final int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
final View child = parent.getChildAt(i);
if (child instanceof ViewGroup) {
findTextViews((ViewGroup) child);
} else if (child instanceof TextView) {
mTargets.add((TextView) child);
}
}
}
private void setupEditorListener() {
final int count = mTargets.size();
for (int i = 0; i < count; i++) {
final TextView target = mTargets.get(i);
target.setOnEditorActionListener(mListener);
}
}
The other possible(and reasonable) solution(like Naveen already mentioned in his comment) is to use one of the ports of the NumberPicker class(or modify the one from the SDK) out there and insert your own widget ids(which will make getting a reference to the widget a simple task). This would be easier to implement now but inconvenient to maintain on the long run.
My search and experimentation has also turned out empty handed. That said I wouldn't encourage this kind of behavior as it doesn't make much sense.
If you need a NumberPicker it is because you want the feature of scrolling to the value that you need, not entering it (though it is possible). If you want to enter the value you'd use an EditText and you would be able to implement what you need without problems.
Alternatively you have to copy NumberPicker implementation from the source and then change it according to your needs (fx by adding ime options).
I have a button to which I attach an onClickListener via code. I have to to this through code because it's in a fragment.
The listener works fine when in landscape mode, but when it's in portrait it doesn't. There's no "click" sound even.
In my xml file, I set the initial visibility of the button to invisible and then make it visible later when the user clicks a radio button in the same Viewgroup as the button. The onclicklisteners of the radiobuttons are working just fine in both portrait and landscape mode.
Now if I remove the "android:visibility="invisible" code in xml, the onclickstener works fine in portrait mode! But of course I need it invisible till the user clicks a radiobutton otherwise the UI doesn't make sense. Very weird indeed.
Here's my code:
private void setOnClickForSaveButton(View v) {
Button changeFundsSave = (Button) v.findViewById(R.id.change_funds_save);
changeFundsSave.setOnClickListener(saveListener);
}
Button.OnClickListener saveListener = new Button.OnClickListener() {
#Override
public void onClick(View v) {
//Get the rootview
View rootView = v.getRootView();
EditText changeFundsEdit = (EditText) rootView.findViewById(R.id.change_funds_edit);
if(changeFundsEdit.getText().toString().equals("")) {
new AlertDialog.Builder(getActivity())
.setTitle( "" )
.setMessage( "Enter the number of units" )
.setPositiveButton( "Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
return;
}
}
};
private void setOnClicksForRadioButtons(View v) {
RadioButton rb1 = (RadioButton)v.findViewById(R.id.add_units);
RadioButton rb2 = (RadioButton)v.findViewById(R.id.remove_units);
RadioButton rb3 = (RadioButton)v.findViewById(R.id.set_units);
rb1.setOnClickListener(addRemoveSetButtonListener);
rb2.setOnClickListener(addRemoveSetButtonListener);
rb3.setOnClickListener(addRemoveSetButtonListener);
}
OnClickListener addRemoveSetButtonListener = new OnClickListener() {
#Override
public void onClick(View v) {
// Since we only have the radiobutton view, we need to get the parent
View rootView = v.getRootView();
//Make the controls visible
TextView changeFundsText = (TextView) rootView.findViewById(R.id.change_funds_text);
EditText changeFundsEdit = (EditText) rootView.findViewById(R.id.change_funds_edit);
Button changeFundsSave = (Button) rootView.findViewById(R.id.change_funds_save);
changeFundsText.setVisibility(View.VISIBLE);
changeFundsEdit.setVisibility(View.VISIBLE);
changeFundsSave.setVisibility(View.VISIBLE);
}
};
}
Solved the problem! In portrait mode, like everyone else I load one fragment in a separate activity. Out of habit I was calling setContentView(something) before loading the fragment! So ultimately the two layouts were overlapping each other and the visible and invisible buttons were overlapping each other and things must have gotten messed up. Damn, I'm not sure if I like the concept of fragments at all. My first time using them. But maybe I just need to learn how to wire them up properly before I get used to them :) Thank you so much for your help
my guess is that
1) do you findViewById again for the view you passed in setOnClickForSaveButton? since the old view will be destroyed and a view will be created when you change screen orientation
2) do you have multiple ids for R.id.change_funds_save
3) add a log at the first line of onclick(v) to see if it is called but goto another branch you didnt expect.
Unless you are loading two separate xml layout files from layout-land and layout-port, there shouldn't be much difference between landscape mode and portrait mode. That being said, I'm going to take a wild guess and say that your app is probably not working correctly due to configuration changes. Let me know if this is actually true... i.e. does your app work at first, but stops working when you rotate the screen?
If this is true, you should look into how the Activity lifecycle is affecting your views and onClickListeners.