I have an alert dialog with a series of checkboxes. The first one is 'Select All'; the others are user options.
How can I programatically change the state of the checkboxes so that when 'Select All' is checked, all the others are also checked, and when one of the others is selected, 'Select All' is unchecked? I can set up the initial state in the configuration, but can't work out how to change the checked state of the boxes on the fly.
Thanks.
But the checkboxes are in an alertdialog so they don't have an id.
Whenever you inflate the custom layout for your alert dialog, you can get the references to the checkboxes via the findViewById() method.
LayoutInflater inflater = LayoutInflater.from(MyActivity.this);
View customView = inflater.inflate(...);
CheckBox selectAll = customView.findViewById(R.id.select_all);
// attach listeners after this.
If you have a lot of complex processing to do, use a DialogFragment instead.
Use DialogFragment and make your own Dialog Layouts.
Extend your activity with FragmentActivity
because getSupportFragmentManager() only work with FragmentActivity
//dialog.setArguments(bundle); if you want to pass values with bundle then use this
If you want to show dialof from FragmentActivity use :
DialogFragment newFragment = H_Calendar_UserScheduleEditFragment
.newInstance(b);
newFragment.show(getSupportFragmentManager(), "dialog");
if you want to show it from fragment:
DialogFragment newFragment = H_Calendar_UserScheduleEditFragment
.newInstance(b);
/** Getting callback from dialog fragment by set target fragment **/
newFragment.setTargetFragment(H_UserCalanderFragment.this, 0);
newFragment.show(getFragmentManager(), "dialog");
public class H_Calendar_UserScheduleEditFragment extends DialogFragment {
Bundle b;
public static H_Calendar_UserScheduleEditFragment newInstance(Bundle b) {
H_Calendar_UserScheduleEditFragment hschedule = new H_Calendar_UserScheduleEditFragment();
hschedule.setArguments(b);
return hschedule;
}
use this method if you want some callback in Activity:
Create your own listner and just pass Activity refrence or fragment refrence to to your listner refrence variable. And on completion or cancelation of dialog do whatever you want from your listner to do.
// Override the Fragment.onAttach() method to instantiate the
// NoticeDialogListener
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
Bundle notificationBundle = getArguments();
// Instantiate the NoticeDialogListener so we can send events to the
// host
//this.mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
Use this if you want callback in Fragment:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
//this.mListener = (NoticeDialogListener) getTargetFragment();
} catch (final ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnCompleteListener");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//To make your dialg fragment to see on full screen , then incude this
getActivity().getWindow().setLayout(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
int style = DialogFragment.STYLE_NO_FRAME;
int theme = R.style.CustomizeDialog;
// int theme = android.R.style.Theme_Wallpaper;
setStyle(style, theme);
b = getArguments();
}
include this style in your style.xml
<style name="CustomizeDialog" parent="android:Theme.Holo.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsFloating">false</item>
</style>
Now in oncreate view
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(
R.layout.my_schedule_calander_userupdatedelete, container,
false);
FindId(v);
SetListner();
return v;
}
///This is all the journey to create your own dialog from fragment or from Activity.
Now you have to implement logic of check selection
Take check boxes in listview and one seperate at top.
check if top check is selected select all checkbox of listview.
otherwise listen for checkseletion in listview.Try and let me know if there comes any problem
Related
I'm trying to make it so a clear button will open up an alert dialog which has a yes or no. When clicking the yes button, it should pass a bool value from the dialog frag to the other frag. If the value is true, which it should be when yes is clicked, it will call methods which will clear a database. Here is the dialog frag and the part of the frag where I'm trying to implement it. I can't get the dialog box to appear, but so far it does make the screen darker which I assume means I'm not hooking it up right.
Dialog frag:
public class DialogClear extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View dialogView = inflater.inflate(R.layout.clear_dialog, null);
final Button yes = dialogView.findViewById(R.id.yes);
final Button no = dialogView.findViewById(R.id.no);
no.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
}
});
yes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
}
});
return builder.create();
}
}
Here is how I'm trying to call it from my frag
clearButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialogClear = new DialogClear();
dialogClear.setTargetFragment(BloodPressureFragment.this, 1);
dialogClear.show(getFragmentManager(),"");
dataManager.clearDatabase();
dataManager.createDatabase();
dataText.setText("");
dataText.setBackgroundResource(R.drawable.no_border);
updateList();
}
});
welcome to code party
you have many choices to do this job, but i will show you best way for using fragments.
As you know, all fragments changes in one activity and extend from it.
So the easy way is this:
1.build public fields in your activity
2.build a getInstant method on activity
3.fill and get values of that activity from any fragments that you want show on this
see this example:
public boolean isLocationOn;
this field is build in activity
now:
in any fragment:
MainActivity.getInstance().isLocationOn = true;
in other fragment:
if(MainActivity.getInstance().isLocationOn){
//todo show map or ...
}
in this way you can use anything in fragments
update me in comments
You should read and try using 3 thing's to solve this.
1. Navigation Component
easy to navigate to fragment's and DialogFragment
2. View Model
Share same View Model between different fragment's of an activity
Data is not lost on Orientation change's
All business logic at one place and easy to unit test
3. Live Data
recommended for responsive ui
Easy to understand Api's
I don't understand DialogFragment at all. How to create one, how to get the user input out of it, and set it into a TextView.
I would like for the TITLE button, when clicked, to bring up a DialogFragment asking the user to enter the title of their Mood Board. The user enters a title. When they click the PostiveButton "Done", the user's title is set into the top left frame of the mood board, which has a TextView with a hint.
Please! Ask questions, because I don't really understand the dialog setup.
Here is a picture of my main_layout, in my MainActivity. Every element has an "#+id/".
The solution you are looking for is a callback:
Create an interface with a method to use as a callback
Implements the interface on the activity
Create the dialog fragment and in onAttach get the interface
Show the dialog fragment on the activity
On dismiss the dialog fragment pass the text using the instance of the interface
interface Callback {
updateText(String text)
}
class CoolActivity... implements Callback
onCreate {
//find your views
showDialogBtn.setOnClickListener(...
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("yourTag");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DialogFragment dialogFragment = ExampleDialogFragment.newInstance();
dialogFragment.show(ft, "yourTag");
)
}
#Override
updateText(String text) {
youtView.setText(text)
}
class CoolDialogFragment extend DialogFragment {
private Callback callback;
#Override
void onAttach(Context context) {
callback = (Callback) context
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.dialog_fragment_example, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//find the views in the dialog fragment
closeBtn.clickListener(...
callback.updateText(edittext.getText().toString())
dismiss()
)
}
}
Here is a gist of a dialog fragment
https://gist.github.com/cutiko/7e307efcf7492ea52ef05cd90f9e3203
The problem is you want to connect a dialog fragment with a another component, and you want to do it straigth forward. This is not considered a good practice because yiu create 2 componentes higly attached, so the best would be to use data persistence and some form of react programming
You can make your mood board title textview static then call it to the alertdialog with edittext to set it text (setText)
like this.
final EditText edittext = new EditText(MainActivity.this);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("Input Title")
.setView(edittext)
.setCancelable(false)
.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
YourCustomDialog.your_title_textviewMoodboard.setText(edittext.getText().toString());
}
})
.setNegativeButton("Back", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.show();
in your custom dialog. declare your textview static globally
public static TextView your_title_textviewMoodboard;
Question:
I'm adding views into a recyclerview with a click. When I click a view it opens a DialogFragment, how do I remove that view through the DialogFragment (by clickign on a button inside it)?
Adapter:
public class SubjectsAdapter extends RecyclerView.Adapter<SubjectsAdapter.ViewHolder> {
public List<String> items = new ArrayList<>();
public Activity mcontext;
public SubjectsAdapter(Activity context) {
this.mcontext=context;
}
public void addItem(String name) {
items.add(name);
notifyItemInserted(items.size() - 1);
}
public void removeItem(int position) {
items.remove(position);
notifyItemRemoved(position);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.grid_item_button, parent, false);
view.requestFocus();
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setButtonName(items.get(position));
}
#Override
public int getItemCount() {
return items.size();
}
int i = 100;
public EditText EditName;
class ViewHolder extends RecyclerView.ViewHolder{
public Button GridButton;
public SharedPreferences prefs;
public ViewHolder(View itemView) {
super(itemView);
GridButton = (Button) itemView.findViewById(R.id.grid_button);
EditName = (EditText) itemView.findViewById(R.id.editName);
ClassName = (TextView) itemView.findViewById(R.id.ClassName);
prefs = mcontext.getPreferences(Context.MODE_PRIVATE);
GridButton.setId(++i);
EditName.requestFocus();
//Showing the DialogFragment
GridButton.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Fragment_Subject_Edit editFragment = Fragment_Subject_Edit.newInstance();
Bundle data = new Bundle();
data.putInt("ID", v.getId());
editFragment.setArguments(data);
editFragment.show(mcontext.getFragmentManager(), "Title");
return false;
}
});
}
public void setButtonName(String buttonName) {
GridButton.setText(buttonName);
}
}
}
Adding views in the activity:
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
final SubjectsAdapter adapter = new SubjectsAdapter(this);
recyclerView.addItemDecoration(new SampleItemDecoration());
recyclerView.setAdapter(adapter);
recyclerView.setItemViewCacheSize(15);
recyclerView.setNestedScrollingEnabled(false);
#Override
public void onClick(View v) {
adapter.addItem(prefs.getString("key1", null));
}
What I have from Lucas Crawford answer, although I'm not getting it right:
1:
public Activity mcontext;
public View.OnLongClickListener LongClicking;
public SubjectsAdapter(Activity context, View.OnLongClickListener longClick) {
this.mcontext = context;
this.LongClicking = longClick;
}
2:
View.OnLongClickListener LongClicker;
...
...
...
adapter = new SubjectsAdapter(this, LongClicker);
recyclerView.setAdapter(adapter);
3:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.grid_item_button, parent, false);
view.setOnLongClickListener(LongClicking);
return new ViewHolder(view);
}
4:
fm = getFragmentManager();
ClassEditor = new Fragment_Subject_Edit();
LongClicker = new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Bundle data = new Bundle();
data.putInt("ID", v.getId());
ClassEditor.setArguments(data);
ClassEditor.show(fm, "Title");
return false;
}
};
Nothing happens when I longClick the button, nor anywhere in the view, what's wrong with these steps, and how to do number 5?
Easy Solution
Instead of assigning the onLongClickListener in the ViewHolder, I would assign the click listener as part of the constructor in the adapter's creation. This way, when you create the view holder in onCreateViewHolder, you give the new view for the view holder the adapter's passed click listener. This is better since it decouples the click event from the ViewHolder's work, as well as letting the activity that created the adapter handle what happens when clicked. (also the dialog fragment created is tied to an Activity lifecycle, why not create it there!).
Next, add a click listener to the dialog fragment's creation, possible as a member variable with a getter/setter. The button in the fragment is then assigned that click listener when you are inflating the dialog fragments view. This way, you do all the click event listening within your Activity, and use the same strategy in both the adapter and dialog fragment.
Can provide code IF required. I hope that makes sense.
Here is a list of what I suggested:
Add a click listener to the constructor of the recycler view adapter.
Pass an onLongClickListener object when you are creating the adapter within your activity.
Assign your view the click listener passed to the adapter in onCreateViewHolder.
Within the click listener created in your activity for the adapter, create the dialog fragment and assign a NEW click listener to handle the button press you desire. This click listener also is apart of the Activity.
When inflating the views in the dialog fragment, give the target button the listener you assigned to the dialog fragment.
The logic of removing the view (or item) from the RecyclerView adapter would be in the click listener you assign to the new dialog fragment. You need a reference to the item currently being removed as well (which you do via arguments).
Advanced Solution
A more advanced solution would be to use something like EventBus which handles listening for events. It cleans up a lot of code to use this. Another one is Otto by Square. It does the same thing, and I personally use Otto for event driven listening rather than passing around click listeners. You can decouple the need for a click listener being passed to your recycler's adapter by just setting a click listener in the adapter that posts an event that your activity is listening for, which then triggers the dialog fragment creation. The dialog fragment would then do the same thing by creating and assigning a new listener within the fragment that posts another event that your activity is listening for related to removing the particular adapter item.
I have an Activity A with a fragment frag2. Inside the fragment I have a RecyclerView and Adapter to show a list of custom class objects. Adding objects to the adapter is handled programmatically. I have a button inside TwoFragment that opens a FragmentDialog. I'd like to add an object to my Adapter by confirming this dialog, but it seems that the adapter is null when called from the FragmentDialog.
The same adapter is not null, and works if I call it from the fragment OnClick.
Moreover the adapter is null only after screen rotation, it works fine before rotating.
To communicate between the two Fragments I implement a communicator class in activity A.
Activity A
public void respond(String type) {
frag2.addSupport(type);
}
frag2
public RecyclerView rv;
public ArrayList<support> supports;
public myAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supports = new ArrayList<>();
adapter = new myAdapter(supports);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate( R.layout.fragment_two, container, false);
layout.setId(R.id.frag2);
if (savedInstanceState!=null)
{
supports = savedInstanceState.getParcelableArrayList("supports");
}
rv = (RecyclerView) layout.findViewById(R.id.rv);
adapter = new myAdapter(supports);
rv.setAdapter(myAdapter);
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
rv.setItemAnimator(new DefaultItemAnimator());
#Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.button1:
addSupport(type); // THIS WORKS ALWAYS, even after screen rotate
break;
case R.id.button2:
showDialog();
break;
}
}
public void showDialog(){
FragmentManager manager = getFragmentManager();
myDialog dialog = new myDialog();
dialog.show(manager, "dialog");
}
public void addSupport(String type){
adapter.addItem(new support(type)); // this line gives null pointer on adapter, but only if called after screen rotate and only if called from the dialog
}
dialog
communicator comm;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog, null);
comm = (myCommunicator) getActivity();
create = (Button) view.findViewById(R.id.button_ok);
create.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.button_ok)
{
// some controls to set type
comm.respond(type)
dismiss();
}
else {
dismiss();
}
myAdapter
public class myAdapter extends RecyclerView.Adapter<myAdapter.VH> {
private LayoutInflater inflater;
private ArrayList<support> data = new ArrayList<>();
// settings for viewholder
public myAdapter (ArrayList<support> data)
{
this.data=data;
}
public void addItem(support dataObj) {
data.add(dataObj);
notifyItemInserted(data.size());
}
}
logcat
FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'myAdapter.addItem(myObject)' on a null object reference
I hope there are no mistakes, I shortened the code for better understanding. Keep in mind that everything works if I never rotate the screen.
I'm a beginner with android and I'm stuck with this for several days now. Please, help.
To understand the problem, it's as you say:
.. everything works if I never rotate the screen
So firstly to understand what happens on rotation, this is a quote from the Android Developer website:
Caution: Your activity will be destroyed and recreated each time the user rotates the screen. When the screen changes orientation, the system destroys and recreates the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout).
Ok, now to understand the error:
FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'myAdapter.addItem(myObject)' on a null object reference
Essentially, in your dialog class, you have created a strong dependency by declaring :
comm = (myCommunicator) getActivity();
because comm references objects which would have been destroyed on rotation, hence the NullPointerException.
To further understand runtime changes, such as orientation changes, I'd recommend going through Handling Runtime Changes.
Update
Thank you for your answer, what would you recommend instead of comm = (myCommunicator) getActivity(); ?
The solution comes in 3 parts:
Make sure the onCreate of Activity A has the following:
#Override
public void onCreate(Bundle savedInstanceState) {
......
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
frag2 = (Frag2) fm.findFragmentByTag(“frag2”);
// create frag2 only for the first time
if (frag2 == null) {
// add the fragment
frag2 = new Frag2();
fm.beginTransaction().add(frag2 , “frag2”).commit();
}
......
}
Add setRetainInstance(true) to the onCreate of frag2.
Remove the implicit referencing i.e. comm = (myCommunicator) getActivity();, and implement something more loosely coupled for dialog.
dialog
public interface Communicator {
void respond(String type);
}
Communicator comm;
....
public void addCommunicator(Communicator communicator) {
comm = communicator;
}
public void removeCommunicator() {
comm = null;
}
#Override
public void onClick(View v) {
if((v.getId()==R.id.button_ok) && (comm!=null))
{
// some controls to set type
comm.respond(type);
}
// Regardless of what button is pressed, the dialog will dismiss
dismiss();
}
This allows you do the following in frag2 (or any other class for that matter):
frag2
<pre><code>
public class Frag2 extends Fragment implements dialog.Communicator {
........
public void showDialog() {
FragmentManager manager = getFragmentManager();
myDialog dialog = new myDialog();
dialog.addCommunicator(this);
dialog.show(manager, "dialog");
}
#Override
public void respond(String type){
adapter.addItem(new support(type));
}
}
I'm using FragmentActivity for switching between Fragment. But I would like to have a Admin Button on a fragment, and when I click on it, a new fragment or activity appears like a child (with the back button in action bar).
How can I make it ?
Here is my code, that works, but the back button doesn't appear in action bar :
Fragment :
public class Reports extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (container == null) {
return null;
}
public void onClick(View v) {
Intent intent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivity(intent);
}
});
}
}
Activity (for the moment... but maybe Fragment if we need ?) :
public class LoginActivity extends ActionBarActivity {
public static final String TAG = LoginActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
Button loginButton = (Button) findViewById(R.id.loginButton);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView emailText = (TextView) findViewById(R.id.emailText);
TextView passwordText = (TextView) findViewById(R.id.passwordText);
ParseUser.logInInBackground(emailText.getText().toString(), passwordText.getText().toString(), new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
Log.i(TAG, "Yeahhh Login OK");
finish();
} else {
runOnUiThread();
}
}
});
}
});
}
Maybe I have to change something in Manifest ?
All you need to do is enable it inside the activity you're currently at.
When inside a FragmentActivity: getActionBar().setHomeAsUpEnabled(boolean).
Otherwise, inside a Fragment: getActivity().getActionBar().setHomeAsUpEnabled(boolean).
U need to override the onCreateOptionsMenu and onOptionsItemSelected. In the onCreateOptionsMenu method do the following : Inflate the menu into the action bar. You can define the contents of the menu item under res/menu folder.
Next in the onOptionsItemSelected method, you can handle the clicks of the back button added in the action bar. Also keep in mind one thing. In the manifest please use a theme which has action bar in it.
Example : Under the application tag use
android:theme="#android:style/Theme.Light" and not anything like android:theme="#android:style/Theme.Light.NoTitleBar
Well if you are starting a new Activity you can enable the back button in it by writing shouldDisplayHomeUp(); in the onCreate() method and on back should take you to the previous activity in the back stack.
And in the other case of adding a new Fragment you can take a look on this answer for reference as it mentions that when you add a new Fragment you add it to the back stack like this
getSupportFragmentManager().beginTransaction()
.add(detailFragment, "detail")
// Add this transaction to the back stack
.addToBackStack()
.commit();
this will make the back button take you to your previous Fragment