Skip to content

Commit

Permalink
2023.05.31 - 1 (migrated to theme colours with material library)
Browse files Browse the repository at this point in the history
  • Loading branch information
fulcrum6378 committed May 31, 2023
1 parent 8101bae commit f7035d7
Show file tree
Hide file tree
Showing 49 changed files with 147 additions and 365 deletions.
107 changes: 0 additions & 107 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,62 +85,15 @@ You can set the layout version using the factory

```java
dpd.setVersion(DatePickerDialog.Version.VERSION_2);
```

The pickers will be themed automatically based on the current theme where they are created, based on the
current `colorAccent`. You can also theme the dialogs via the `setAccentColor(int color)` method. Alternatively, you can
theme the pickers by overwriting the color resources `accent_color` and `accent_color_dark` in your project.

```xml

<color name="accent_color">#009688</color>
<color name="accent_color_dark">#00796b</color>
```

The exact order in which colors are selected is as follows:

1. `setAccentColor(int color)` in java code
2. `android.R.attr.colorAccent` (if android 5.0+)
3. `R.attr.colorAccent` (eg. when using AppCompat)
4. `R.color.accent_color` and `R.color.accent_color_dark` if none of the others are set in your project

The pickers also have a dark theme. This can be specified globablly using the `theme_dark` attribute in your theme
or the `setThemeDark(boolean themeDark)` functions. The function calls overwrite the XML setting.

```xml

<item name="theme_dark">true</item>
```

## Additional Options

### [All] `setThemeDark(boolean themeDark)`

The dialogs have a dark theme that can be set by calling

```java
dialog.setThemeDark(true);
```

### [All] `setAccentColor(String color)` and `setAccentColor(int color)`

Set the accentColor to be used by the Dialog. The String version parses the color out using `Color.parseColor()`. The
int version requires a ColorInt bytestring. It will explicitly set the color to fully opaque.

### [All] `setOkColor()` and `setCancelColor()`

Set the text color for the OK or Cancel button. Behaves similar to `setAccentColor()`

### [TimePickerDialog] `setTitle(String title)`

Shows a title at the top of the `TimePickerDialog`

### [DatePickerDialog] `setTitle(String title)`

Shows a title at the top of the `DatePickerDialog` instead of the day of the week

### [All] `setOkText()` and `setCancelText()`

Set a custom text for the dialog Ok and Cancel labels. Can take a resourceId of a String. Works in both the
DatePickerDialog and TimePickerDialog

Expand Down Expand Up @@ -391,66 +344,6 @@ class MyDateRangeLimiter implements DateRangeLimiter {
When you provide a custom `DateRangeLimiter` the built-in methods for setting the enabled / disabled dates will no
longer work. It will need to be completely handled by your implementation.

### Why do the OK and Cancel buttons have the accent color as a background when combined with the Material Components library

[Material Components](https://github.com/material-components/material-components-android) replaces all instances
of `Button` with an instance of `MaterialButton` when using one of its regular
themes: https://github.com/material-components/material-components-android/blob/master/docs/getting-started.md#material-components-themes
The default version of `MaterialButton` uses `colorPrimary` as the background color. Because Material Components
replaces the View replacer with their own implementation there is not much I can do to fix this from this library.

There are a few workarounds:

* Use one of the bridge themes, which do not replace the View Inflater
* Overwrite the style of the mdtp buttons with one that inherits from Material Components text buttons, as
described [here](https://github.com/wdullaer/MaterialDateTimePicker/issues/523#issuecomment-477349333):
```xml
<style name="ActionButton.Text" parent="Widget.MaterialComponents.Button.TextButton.Dialog"/>
```
* Overwrite the View inflater again in your application theme by adding the following statement in your application
theme:
```xml
<item name="viewInflaterClass">androidx.appcompat.app.AppCompatViewInflater</item>
```
You will then need to explicitly use `MaterialButton` in your application rather than `Button`

### Why are my callbacks lost when the device changes orientation?

The simple solution is to dismiss the pickers when your activity is paused.

```java
tpd.dismissOnPause(true);
```

If you do wish to retain the pickers when an orientation change occurs, things become a bit more tricky.

By default, when an orientation changes occurs android will destroy and recreate your entire `Activity`. Wherever
possible this library will retain its state on an orientation change. The only notable exceptions are the different
callbacks and listeners. These interfaces are often implemented on `Activities` or `Fragments`. Naively trying to retain
them would cause memory leaks. Apart from explicitly requiring that the callback interfaces are implemented on
an `Activity`, there is no safe way to properly retain the callbacks, that I'm aware off.

This means that it is your responsibility to set the listeners in your `Activity`'s `onResume()` callback.

```java
@Override
public void onResume() {
super.onResume();

DatePickerDialog dpd = (DatePickerDialog) getFragmentManager().findFragmentByTag("Datepickerdialog");
TimePickerDialog tpd = (TimePickerDialog) getFragmentManager().findFragmentByTag("TimepickerDialog");

if(tpd != null) tpd.setOnTimeSetListener(this);
if(dpd != null) dpd.setOnDateSetListener(this);
}
```

## Potential Improvements

* Landscape timepicker can use some improvement
* Code cleanup: there is a bit too much spit and ductape in the tweaks I've done.
* Document all options on both pickers

## License

Copyright (c) 2015 Wouter Dullaert
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ org.gradle.unsafe.configuration-cache=false
ANDROID_BUILD_MIN_SDK_VERSION=24
ANDROID_BUILD_SDK_VERSION=33
ANDROID_BUILD_TARGET_SDK_VERSION=33
VERSION_CODE=5
VERSION_NAME=2.5
VERSION_CODE=6
VERSION_NAME=2.7
1 change: 1 addition & 0 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'com.google.android.material:material:1.9.0'
}

afterEvaluate { // You only need to set the access token and execute "gradle publish"...
Expand Down
10 changes: 7 additions & 3 deletions library/src/main/java/ir/mahdiparastesh/mcdtp/McdtpUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
Expand Down Expand Up @@ -64,7 +66,8 @@ public static ObjectAnimator getPulseAnimator(View labelToAnimate, float decreas

@SuppressWarnings("unused")
public static int dpToPx(float dp, Resources resources) {
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
return (int) px;
}

Expand All @@ -75,9 +78,10 @@ public static int darkenColor(int color) {
return Color.HSVToColor(hsv);
}

public static int getAccentColorFromThemeIfAvailable(Context context) {
@ColorInt
public static int themeColor(Context context, @AttrRes int res) {
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
context.getTheme().resolveAttribute(res, typedValue, true);
return typedValue.data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,41 @@

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.content.ContextCompat;

public class TextViewWithCircularIndicator extends AppCompatTextView {

private static final int SELECTED_CIRCLE_ALPHA = 255;

final Paint mCirclePaint = new Paint();

private int mCircleColor;
private final String mItemIsSelectedText;

private boolean mDrawCircle;

public TextViewWithCircularIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
mCircleColor = ContextCompat.getColor(context, R.color.accent_color);
mItemIsSelectedText = context.getResources().getString(R.string.item_is_selected);

init();
}

private void init() {
mCirclePaint.setFakeBoldText(true);
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setColor(McdtpUtils.themeColor(getContext(),
com.google.android.material.R.attr.colorOnSurface));
mCirclePaint.setTextAlign(Align.CENTER);
mCirclePaint.setStyle(Style.FILL);
mCirclePaint.setAlpha(SELECTED_CIRCLE_ALPHA);
}

public void setAccentColor(int color) {
mCircleColor = color;
mCirclePaint.setColor(mCircleColor);
setTextColor(createTextColor(color));
}

private ColorStateList createTextColor(int accentColor) {
int[][] states = new int[][]{
new int[]{android.R.attr.state_pressed}, // pressed
new int[]{android.R.attr.state_selected}, // selected
new int[]{}
};
int[] colors = new int[]{
accentColor, Color.WHITE, McdtpUtils.night(getContext()) ? Color.WHITE : Color.BLACK
};
return new ColorStateList(states, colors);
}

public void drawIndicator(boolean drawCircle) {
mDrawCircle = drawCircle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ public interface DatePickerController<CAL extends Calendar> extends FontCustomis

MonthAdapter.CalendarDay<CAL> getSelectedDay();

int getAccentColor();

boolean isHighlighted(int year, int month, int day);

int getFirstDayOfWeek();
Expand Down
Loading

0 comments on commit f7035d7

Please sign in to comment.