I want to change DatePickerDialogs and TimePickerDialogs globally using their spinner style. For that case I added android:datePickerStyle and android:timePickerStyle to my AppTheme. When I was testing the style changes, everything is fine on a virtual emulated Nexus device. But when I test it on an Samsung device, there where noch changed styles loaded. Both devices run with Nougat.
Here is a snippet from my style.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="android:datePickerStyle">#style/AppTheme.DatePicker</item>
<item name="android:timePickerStyle">#style/AppTheme.TimePicker</item>
</style>
<style name="AppTheme.DatePicker" parent="android:Widget.DatePicker">
<item name="android:spinnersShown">true</item>
<item name="android:calendarViewShown">false</item>
</style>
<style name="AppTheme.TimePicker" parent="android:Widget.Material.TimePicker">
<item name="android:timePickerMode">spinner</item>
</style>
And that is the way I call the DatePickerDialog. (The TimePickerDialogs are called the same way)
DatePickerDialog datePickerDialog = new DatePickerDialog(
getView().getContext(), SettingsFragment.this, 2000 , 10, 1);
datePickerDialog.show();
Settings.Fragment is the fragment that calls the dialogs.
This it how it should look
Nexus device
This it how it should not look
Samsung device
Edit:
The Nexus device is a virtual emulated Nexus 5X with Android 7.1.1 and the Samsung device is a Samsung S7 Edge wit Android 7.0.
I found a workaround for the problem myself.
The workaround is not to use the global styles. Instead I had to write my own DatePickerDialog.
In the custom dialog layout I could use the DatePicker preferences I wanted. This looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<DatePicker
android:id="#+id/spinnerDatePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:datePickerMode="spinner"
android:focusable="true"
android:spinnersShown="true" />
</LinearLayout>
The custom dialog looks like the following:
public class SpinnerDatePickerDialog extends DialogFragment {
private ISpinnerDatePickerDialogListener listener;
private DatePicker datePicker;
// this is no clean android fragment constructor, but we want to use it here
#SuppressLint("ValidFragment")
public SpinnerDatePickerDialog(ISpinnerDatePickerDialogListener listener) {
super();
this.listener = listener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Build the dialog and set up the button click handlers
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_date, null);
datePicker = (DatePicker) view.findViewById(R.id.spinnerDatePicker);
datePicker.updateDate(defaultYear, defaultMonth, defaultDay);
builder.setView(view);
builder
.setPositiveButton(R.string.submit, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the positive button event back to the host activity
listener.onSpinnerDateDialogPositiveClick(SpinnerDatePickerDialog.this);
}
})
.setNegativeButton(R.string.abort, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the negative button event back to the host activity
listener.onSpinnerDateDialogNegativeClick(SpinnerDatePickerDialog.this);
}
});
return builder.create();
}
}
To send values to the original fragment, I created an interface. The original fragment implements this interface and the custom dialog gets the fragment as an parameter in his constructor. This way I can trigger the listener in the original fragment.
The interface:
public interface ISpinnerDatePickerDialogListener {
void onSpinnerDateDialogPositiveClick(SpinnerDatePickerDialog dialog);
void onSpinnerDateDialogNegativeClick(SpinnerDatePickerDialog dialog);
}
The fragment class that calls the dialog:
public class SettingsFragment extends Fragment implements ISpinnerDatePickerDialogListener, ISpinnerTimePickerDialogListener {
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// initialize listeners for text inputs, to open picker dialogs
periodBegin = (EditText) getView().findViewById(R.id.editPeriodBegin);
periodBegin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showDialog(PERIOD_BEGIN_DIALOG_ID);
}
});
}
/**
* opens dialog for id
*
* #param id
*/
private void showDialog(int id) {
switch(id) {
case PERIOD_BEGIN_DIALOG_ID:
SpinnerDatePickerDialog datePickerDialog;
datePickerDialog = new SpinnerDatePickerDialog(this);
datePickerDialog.show(getFragmentManager(), datePickerDialog.getTAG());
break;
}
#Override
public void onSpinnerDateDialogPositiveClick(SpinnerDatePickerDialog dialog) {
// TODO send DatePicker values with listener
// load DatePicker from dialog and set them to EditText text
DatePicker datePicker = dialog.getDatePicker();
int day = datePicker.getDayOfMonth();
int month = datePicker.getMonth();
int year = datePicker.getYear();
// TODO
String formattedDate = FORMAT.format(new Date(year - 1900, month, day));
periodBegin.setText(formattedDate);
}
#Override
public void onSpinnerDateDialogNegativeClick(SpinnerDatePickerDialog dialog) {
// Nothing to do here
}
}
Related
This is the error in the Google Play Store
java.lang.IllegalArgumentException:
at android.view.WindowManagerGlobal.findViewLocked (WindowManagerGlobal.java:572)
at android.view.WindowManagerGlobal.removeView (WindowManagerGlobal.java:476)
at android.view.WindowManagerImpl.removeViewImmediate (WindowManagerImpl.java:144)
at android.app.Dialog.dismissDialog (Dialog.java:389)
at android.app.Dialog.dismiss (Dialog.java:371)
at com.master.azkarmorningevening.LoadingDialog.dismissDialog (LoadingDialog.java)
at com.master.azkarmorningevening.-$$Lambda$hxi6xW-58LrFqQAbkmexCKkt5eY.run(lambda)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:236)
at android.app.ActivityThread.main (ActivityThread.java:8060)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:656)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:967)
The class that i create Dialog
class LoadingDialog {
Activity activity;
private AlertDialog dialog;
LoadingDialog(Activity myActivity){
activity = myActivity;
}
#SuppressLint("InflateParams")
void StartLoadingAlertDialog(){
AlertDialog.Builder builder = new
AlertDialog.Builder(activity,R.style.full_sereen_mood);
LayoutInflater inflater = activity.getLayoutInflater();
builder.setView(inflater.inflate(R.layout.splash,null));
builder.setCancelable(false);
dialog = builder.create();
dialog.show();
}
void dismissDialog(){
dialog.dismiss();
}
}
i get function from class LoandinDailog
with Handler
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoadingDialog loadingDialog = new LoadingDialog(MainActivity.this);
loadingDialog.StartLoadingAlertDialog();
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(loadingDialog::dismissDialog,3000);
}
}
Make Style for Dialog for class LoadingDialog
To define some properties
parent="Theme.AppCompat.DayNight.DarkActionBar"
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:windowFullscreen">true</item>
<item name="windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
</style>
Short answer: You need to place the part below inside onResume()
LoadingDialog loadingDialog = new LoadingDialog(MainActivity.this);
loadingDialog.StartLoadingAlertDialog();
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(loadingDialog::dismissDialog,3000);
With that done, the splash screen will appear every time the UI thread resumes, which is going to be annoying, so you'll need to have a flag that tells you whether the splash screen was already shown, or not, and check for that condition before you execute that block of code inside onResume()
Longer answer: You need to watch some videos on youtube from Google IO about the Activity lifecycle. Those Android fundamentals are very important and they can not be fully explained in a page or two.
https://www.youtube.com/watch?v=bEKNi1JOrNs
I am a beginner Android developer and I have been struggling the issue that I can't see the toolbar in any activity that inherits Base Activity. According to other resource, to use the same toolbar in the different activities. I have to implement it in Base Activity and inherit it where I need to use it. Could anyone help me figure out the problem?
styles.xml
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
<style name="AppTheme" parent="AppBaseTheme">
</style>
</resources>
quiz.menu.xml inside of menu folder
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/contact"
android:icon="#drawable/ic_contacts_black_24dp"
android:title="Contact"
app:showAsAction="ifRoom" />
<item android:id="#+id/language"
android:title="Language"
app:showAsAction="never" />
<item android:id="#+id/speech"
android:title="Speech"
app:showAsAction="never">
<munu>
<item android:id="#+id/subitem1"
android:title="Sub Item 1"/>
<item android:id="#+id/subitem2"
android:title="Sub Item 2"/>
</munu>
</item>
</menu>
BaseActivity
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.quiz_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.contact:
Toast.makeText(this, "Contact is selected", Toast.LENGTH_SHORT).show();
return true;
case R.id.language:
Toast.makeText(this, "Language is selected", Toast.LENGTH_SHORT).show();
return true;
case R.id.speech:
Toast.makeText(this, "Speech is selected", Toast.LENGTH_SHORT).show();
return true;
case R.id.subitem1:
Toast.makeText(this, "Language is selected", Toast.LENGTH_SHORT).show();
return true;
case R.id.subitem2:
Toast.makeText(this, "Speech is selected", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
WelcomeActivity (inherits base Activity)
public class WelcomeActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
final Button databaseButton = findViewById(R.id.database);
databaseButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Code here executes on main thread after user presses button
Intent databaseIntent = new Intent(WelcomeActivity.this, Questionnaire.class);
startActivity(databaseIntent);
}
});
}
Questionnaire
public class Questionnaire extends BaseActivity {
public Spinner languageSpinner;
public int languageId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_questionnaire);
...
}
}
The answer is actually simple. You firstly set contentview in OnCreate() method of the BaseActivity class, then you change the view to another xml file in OnCreate() methods of the child classes.
What I suggest is that you do not implement OnCreate() method in BaseActivity class but implement SetContentView() method in BaseActivity.
In short, delete onCreate() method from BaseActivity() and add setContentView() method in the below.
#Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
P.S - Your quiz_menu.xml file does not look like a menu file. :)
P.P.S - Let me know if it works, or if you have troubles. :)
This is my Starting Activity. It is working fine programmatically.
The only problem which I'm facing is that the OverFlow-Menu comes is dark theme when called by the Hardware Menu key.
I've provided all the essential lines of code in this sample.
public class StartingActivity extends AppCompatActivity implements LoginActivity_Tab.loginActivityTab_interface {
private static final String LOGIN_URL = "http://rollhack.96.lt/login.php";
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
private TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_starting);
includeWidgets();
}
private void includeWidgets() {
///// Tab Layout /////
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
setupViewPager(mViewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
///// ToolBar /////
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle("Note Pad");
}
///// This method is called for Exiting the App /////
public void exitApp() {
final AlertDialog.Builder exit = new AlertDialog.Builder(StartingActivity.this);
exit.setTitle("Exit Application")
.setMessage("Are you sure you want to Exit the application?")
.setCancelable(true)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
StartingActivity.this.finishAffinity();
}
})
.setNegativeButton(android.R.string.no, null);
exit.create().show();
}
///// This method is called to assign the Key Events /////
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
exitApp();
return true;
}
return super.onKeyUp(keyCode, event);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_starting_activity, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings:
return Boolean.parseBoolean(null);
case (R.id.menu_about):
return Boolean.parseBoolean(null);
case (R.id.menu_exit):
exitApp();
return true;
}
return super.onOptionsItemSelected(item);
}
This is how it looks when it is called by the overflow menu icon of the ActionBar
This is how my App OverFlow-Menu looks when Hardware Menu key is pressed
Overflow menu by Icon
You can change the color of the overflow menu background by adding a new style in style.xml.
<style name="OverflowMenu"
parent="#android:style/Theme.Holo">
<item name="android:popupMenuStyle">#style/MyOverflowMenu</item>
<item name="android:itemTextAppearance">#style/TextAppearance</item>
</style>
<style name="MyOverflowMenu"
parent="#android:style/Widget.Holo.ListPopupWindow">
<item name="android:popupBackground">#color/your_color</item>
</style>
<style name="TextAppearance">
<item name="android:textColor">#color/your_color</item>
</style>
Overflow Menu by Hardware Key
To change the color of Overflow menu called by Hardware key, add another style.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="actionBarPopupTheme">#style/OverflowMenuHardware</item>
</style>
<style name="OverflowMenuHardware" parent="ThemeOverlay.AppCompat.Dark">
<item name="android:textColorSecondary">#color/your_color</item>
<item name="android:colorBackground">#color/your_color</item>
</style>
Implement either one of these to change the color of Overflow menu of either the one called by icon(former code) or by hardware key(latter code).
I have a code sample got from the internet and the code goes like this
ListView lv1;
lv1 = (ListView) findViewById(R.id.custom_list);
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
// print toast
}
});
Well I want to show context menu on list item click and I don't know how to do that.
You can use PopupMenu.
Create popup.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_action1"
android:icon="#drawable/menu_action1"
android:title="#string/menu_action1" />
...
</menu>
and add this to onItemClick:
PopupMenu popup = new PopupMenu(this, v);
// this = your activity
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.actions);
popup.show();
In addition your Activity should implements OnMenuItemClickListener so you can get menu click callback.
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