可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to change color of the blue dividers for a DatePicker in a dialog. This is just a normal DialogFragment with a DatePicker and a ButtonBar.
Does anyone know to change these dividers, or if it's even possible without replacing the entire DatePicker with a custom one?
Mini rant
Now I've seen too many answers suggesting the following code:
<style name="datePickerTheme" parent="@android:style/Widget.DeviceDefault.DatePicker">
<item name="android:divider">**your @drawable/ or @color/ here**</item>
</style>
Which simply does not work. Have you guys tried this before suggesting this code? It should work perfectly, but it does not seem to work with the DatePicker.
回答1:
The following approach worked for me.This sets divider colours for all fields (also for am/pm)
private void applyStyLing(TimePickerDialog timePickerDialog){
Resources system = Resources.getSystem();
int hourNumberPickerId = system.getIdentifier("hour", "id", "android");
int minuteNumberPickerId = system.getIdentifier("minute", "id", "android");
int ampmNumberPickerId = system.getIdentifier("amPm", "id", "android");
NumberPicker hourNumberPicker = (NumberPicker) timePickerDialog.findViewById(hourNumberPickerId);
NumberPicker minuteNumberPicker = (NumberPicker) timePickerDialog.findViewById(minuteNumberPickerId);
NumberPicker ampmNumberPicker = (NumberPicker) timePickerDialog.findViewById(ampmNumberPickerId);
setNumberPickerDividerColour(hourNumberPicker);
setNumberPickerDividerColour(minuteNumberPicker);
setNumberPickerDividerColour(ampmNumberPicker);
}
private void setNumberPickerDividerColour(NumberPicker number_picker){
final int count = number_picker.getChildCount();
for(int i = 0; i < count; i++){
try{
Field dividerField = number_picker.getClass().getDeclaredField("mSelectionDivider");
dividerField.setAccessible(true);
ColorDrawable colorDrawable = new ColorDrawable(mContext.getResources().getColor(R.color
.interactive_color));
dividerField.set(number_picker,colorDrawable);
number_picker.invalidate();
}
catch(NoSuchFieldException e){
Log.w("setNumberPickerTxtClr", e);
}
catch(IllegalAccessException e){
Log.w("setNumberPickerTxtClr", e);
}
catch(IllegalArgumentException e){
Log.w("setNumberPickerTxtClr", e);
}
}
}
回答2:
I solved this by doing this:
I changed the DatePicker
divider with reflection by finding the "mSelectionDivider
". Then I had problems with the Title divider looking stupid, so i added a textview
above the LinearLayout
containing the 3 datepickers
and used newFragment.setTitle("");
to remove the original one.
Example for divider drawable: Credits to the guy who made this! :)
http://ge.tt/8wK7TZ71/v/0?c
Result picture <-My result
Example:
public DatePickerDialog makeDatePicker(OnDateSetListener listener, Calendar cal) {
Calendar c;
if (cal == null) {
c = Calendar.getInstance();
} else {
c = cal;
}
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog newFragment = new DatePickerDialog(this, listener, year, month, day);
// removes the original topbar:
newFragment.setTitle("");
// Divider changing:
DatePicker dpView = newFragment.getDatePicker();
LinearLayout llFirst = (LinearLayout) dpView.getChildAt(0);
LinearLayout llSecond = (LinearLayout) llFirst.getChildAt(0);
for (int i = 0; i < llSecond.getChildCount(); i++) {
NumberPicker picker = (NumberPicker) llSecond.getChildAt(i); // Numberpickers in llSecond
// reflection - picker.setDividerDrawable(divider); << didn't seem to work.
Field[] pickerFields = NumberPicker.class.getDeclaredFields();
for (Field pf : pickerFields) {
if (pf.getName().equals("mSelectionDivider")) {
pf.setAccessible(true);
try {
pf.set(picker, getResources().getDrawable(R.drawable.np_numberpicker_selection_divider_orange));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
}
// New top:
int titleHeight = 90;
// Container:
LinearLayout llTitleBar = new LinearLayout(this);
llTitleBar.setOrientation(LinearLayout.VERTICAL);
llTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, titleHeight));
// TextView Title:
TextView tvTitle = new TextView(this);
tvTitle.setText("Select a date");
tvTitle.setGravity(Gravity.CENTER);
tvTitle.setPadding(10, 10, 10, 10);
tvTitle.setTextSize(24);
tvTitle.setTextColor(Color.BLACK);
tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, titleHeight-2));
llTitleBar.addView(tvTitle);
// View line:
View vTitleDivider = new View(this);
vTitleDivider.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 2));
vTitleDivider.setBackgroundColor(getResources().getColor(R.color.crumblrOrange));
llTitleBar.addView(vTitleDivider);
dpView.addView(llTitleBar);
FrameLayout.LayoutParams lp = (android.widget.FrameLayout.LayoutParams) llFirst.getLayoutParams();
lp.setMargins(0, titleHeight, 0, 0);
return newFragment;
}
回答3:
I based this code on Ajit's answer, but I tweaked it for DatePicker
rather than TimePicker
. Moreover, I added a null
check just to stay on the safe side:
public static void colorizeDatePicker(DatePicker datePicker) {
Resources system = Resources.getSystem();
int dayId = system.getIdentifier("day", "id", "android");
int monthId = system.getIdentifier("month", "id", "android");
int yearId = system.getIdentifier("year", "id", "android");
NumberPicker dayPicker = (NumberPicker) datePicker.findViewById(dayId);
NumberPicker monthPicker = (NumberPicker) datePicker.findViewById(monthId);
NumberPicker yearPicker = (NumberPicker) datePicker.findViewById(yearId);
setDividerColor(dayPicker);
setDividerColor(monthPicker);
setDividerColor(yearPicker);
}
private static void setDividerColor(NumberPicker picker) {
if (picker == null)
return;
final int count = picker.getChildCount();
for (int i = 0; i < count; i++) {
try {
Field dividerField = picker.getClass().getDeclaredField("mSelectionDivider");
dividerField.setAccessible(true);
ColorDrawable colorDrawable = new ColorDrawable(picker.getResources().getColor(R.color.colorAccent));
dividerField.set(picker, colorDrawable);
picker.invalidate();
} catch (Exception e) {
Log.w("setDividerColor", e);
}
}
}
Output
回答4:
This fixed my problem adding below line of code to App theme style.
<item name="colorControlNormal">@color/colorAccent</item>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorControlNormal">@color/blue</item>
</style>
回答5:
Take into account:
You don't need a new R.drawable.divider
you can write:
pf.set(number_picker, new ColorDrawable(getResources().getColor(R.color.red)));
回答6:
This version is adjusted for specific use with DatePicker. While Andrea Lazzarotto's version works fine, it uses an unnecessary loop which leads to multiple appliance of the color change. Besides minor code improvements, my version uses the app theme's primary color to match the divider color (see How can I get the primary color from my app theme?). Tested with Android 6.0 and 8.0:
private void colorizeDatePicker(final DatePicker datePicker) {
final Resources system = Resources.getSystem();
final String defType = "id";
final String defPackage = "android";
final int dayId = system.getIdentifier("day", defType, defPackage);
final int monthId = system.getIdentifier("month", defType, defPackage);
final int yearId = system.getIdentifier("year", defType, defPackage);
final NumberPicker dayPicker = (NumberPicker) datePicker.findViewById(dayId);
final NumberPicker monthPicker = (NumberPicker) datePicker.findViewById(monthId);
final NumberPicker yearPicker = (NumberPicker) datePicker.findViewById(yearId);
setDividerColor(dayPicker);
setDividerColor(monthPicker);
setDividerColor(yearPicker);
}
private void setDividerColor(final NumberPicker picker) {
if (picker == null) {
return;
}
try {
final Field dividerField = picker.getClass().getDeclaredField("mSelectionDivider");
dividerField.setAccessible(true);
final TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.colorPrimary, outValue, true);
final int dividerColor = outValue.data;
dividerField.set(picker, new ColorDrawable(dividerColor));
picker.invalidate();
} catch (Exception e) {
}
}
回答7:
Yes of course you can. You can use these attributes for instance:
<NumberPicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
selectionDivider="@color/black" //The divider for making the selection area
selectionDividerHeight="1px"//The height of the selection divider
selectionDividersDistance="3dp"//The distance between the two selection dividers
internalLayout="@layout/something"//The layout of the number picker.
internalMaxHeight="5dp"//The max height of the NumberPicker (also check other variations)
internalMinWidth="5dp" // The max width of the NumberPicker (also check other variations)
virtualButtonPressedDrawable="@drawable/something"//The drawable for pressed virtual (increment/decrement) buttons.
/>
Update :
You can use this custom datepicker. It's highly customizable and backward competiable. It basically uses numberpicker and you can set divider using attributes above.
回答8:
Thanks Mvj for solving the problem! Just thought I'd also show my implementation of your solution on the timepickers' dividers.
TimePickerDialog ptd = new TimePickerDialog(getActivity(), R.style.PickerStyler, this, hour, minute,DateFormat.is24HourFormat(getActivity()));
ptd.setTitle("");
//Needs to be try catched
Field mTimePickerField = ptd.getClass().getDeclaredField("mTimePicker");
mTimePickerField.setAccessible(true);
TimePicker mTimePickerInstance = (TimePicker) mTimePickerField.get(ptd);
LinearLayout llFirst = (LinearLayout) mTimePickerInstance.getChildAt(0);
LinearLayout llSecond = (LinearLayout) llFirst.getChildAt(0);
boolean continiue = false;
NumberPicker picker = null;
for (int i = 0; i < llSecond.getChildCount(); i++) {
continiue = true;
try{picker = (NumberPicker) llSecond.getChildAt(i);
}catch(Exception e){continiue = false;}
if(continiue){
Field[] pickerFields = NumberPicker.class.getDeclaredFields();
for (Field pf : pickerFields) {
if (pf.getName().equals("mSelectionDivider")) {
pf.setAccessible(true);
try {
pf.set(picker, getResources().getDrawable(R.drawable.divider));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
}
}