我想为我的日期选择器和时间选择器使用自定义皮肤。在XML中更改背景并不能解决问题(它只更改了设置的背景,而不是每个按钮的背景)。API非常简短,没有关于外观方面的内容(http://developer.android.com/reference/android/widget/DatePicker.html)。是否可以为日期选择器和时间选择器的按钮使用自定义皮肤?
我想为我的日期选择器和时间选择器使用自定义皮肤。在XML中更改背景并不能解决问题(它只更改了设置的背景,而不是每个按钮的背景)。API非常简短,没有关于外观方面的内容(http://developer.android.com/reference/android/widget/DatePicker.html)。是否可以为日期选择器和时间选择器的按钮使用自定义皮肤?
好的,您正在寻找日期选择器和时间选择器的自定义主题。这将允许您更改按钮的主题..
https://github.com/luminousman/DatePicker
并且以ICS风格为例
https://github.com/luminousman/android-datepicker
希望这可以帮助您....
这种方法并不安全,但我相信这是在不复制整个类的情况下自定义时间选择器的唯一方法:
try { for (int i=0; i<2; i++)
{
((ViewGroup) ((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(i)).getChildAt(0).setBackgroundResource(R.drawable.timepicker_up_btn);
((ViewGroup) ((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(i)).getChildAt(1).setBackgroundResource(R.drawable.timepicker_input);
((ViewGroup) ((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(i)).getChildAt(2).setBackgroundResource(R.drawable.timepicker_down_btn);
}
} catch (Throwable t) {/* obviously no the view may look like garbage */}
很不幸,NumberPicker是一个内部小部件。需要覆盖这些背景。而且没有官方的方法来做到这一点。
<NumberPickerButton android:id="@+id/increment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/timepicker_up_btn" />
<EditText android:id="@+id/timepicker_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:singleLine="true"
style="?android:attr/textAppearanceLargeInverse"
android:textColor="@android:color/primary_text_light"
android:textSize="30sp"
android:background="@drawable/timepicker_input" />
<NumberPickerButton android:id="@+id/decrement"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/timepicker_down_btn" />
package com.pointnormal;
import java.util.Calendar;
import android.content.Context;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class DateTimePicker extends RelativeLayout
{
private int startYear = 1900;
private int endYear = 2100;
private View myPickerView;
private Button month_plus;
private EditText month_display;
private Button month_minus;
private Button date_plus;
private EditText date_display;
private Button date_minus;
private Button year_plus;
private EditText year_display;
private Button year_minus;
private Button hour_plus;
private EditText hour_display;
private Button hour_minus;
private Button min_plus;
private EditText min_display;
private Button min_minus;
private Calendar cal;
// Constructor start
public DateTimePicker(Context context)
{
this(context, null);
init(context);
}
public DateTimePicker(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public DateTimePicker(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myPickerView = inflator.inflate(R.layout.datetimepicker, null);
this.addView(myPickerView);
initializeReference();
}
private void init(Context mContext)
{
LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myPickerView = inflator.inflate(R.layout.datetimepicker, null);
this.addView(myPickerView);
initializeReference();
}
private void initializeReference()
{
month_plus = (Button) myPickerView.findViewById(R.id.month_plus);
month_plus.setOnClickListener(month_plus_listener);
month_display = (EditText) myPickerView.findViewById(R.id.month_display);
month_minus = (Button) myPickerView.findViewById(R.id.month_minus);
month_minus.setOnClickListener(month_minus_listener);
date_plus = (Button) myPickerView.findViewById(R.id.date_plus);
date_plus.setOnClickListener(date_plus_listener);
date_display = (EditText) myPickerView.findViewById(R.id.date_display);
date_display.addTextChangedListener(date_watcher);
date_minus = (Button) myPickerView.findViewById(R.id.date_minus);
date_minus.setOnClickListener(date_minus_listener);
year_plus = (Button) myPickerView.findViewById(R.id.year_plus);
year_plus.setOnClickListener(year_plus_listener);
year_display = (EditText) myPickerView.findViewById(R.id.year_display);
year_display.setOnFocusChangeListener(mLostFocusYear);
year_display.addTextChangedListener(year_watcher);
year_minus = (Button) myPickerView.findViewById(R.id.year_minus);
year_minus.setOnClickListener(year_minus_listener);
hour_plus = (Button) myPickerView.findViewById(R.id.hour_plus);
hour_plus.setOnClickListener(hour_plus_listener);
hour_display = (EditText) myPickerView.findViewById(R.id.hour_display);
hour_display.addTextChangedListener(hour_watcher);
hour_minus = (Button) myPickerView.findViewById(R.id.hour_minus);
hour_minus.setOnClickListener(hour_minus_listener);
min_plus = (Button) myPickerView.findViewById(R.id.min_plus);
min_plus.setOnClickListener(min_plus_listener);
min_display = (EditText) myPickerView.findViewById(R.id.min_display);
min_display.addTextChangedListener(min_watcher);
min_minus = (Button) myPickerView.findViewById(R.id.min_minus);
min_minus.setOnClickListener(min_minus_listener);
initData();
initFilterNumericDigit();
}
public void initData()
{
cal = Calendar.getInstance();
month_display.setText(months[cal.get(Calendar.MONTH)]);
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
hour_display.setText(String.valueOf(cal.get(Calendar.HOUR_OF_DAY)));
min_display.setText(String.valueOf(cal.get(Calendar.MINUTE)));
}
private void initFilterNumericDigit()
{
try {
date_display.setFilters(new InputFilter[] { new InputFilterMinMax(1, cal.getActualMaximum(Calendar.DAY_OF_MONTH)) });
InputFilter[] filterArray_year = new InputFilter[1];
filterArray_year[0] = new InputFilter.LengthFilter(4);
year_display.setFilters(filterArray_year);
hour_display.setFilters(new InputFilter[] { new InputFilterMinMax(0, 23) });
min_display.setFilters(new InputFilter[] { new InputFilterMinMax(0, 59) });
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void changeFilter()
{
try {
date_display.setFilters(new InputFilter[] { new InputFilterMinMax(1, cal.getActualMaximum(Calendar.DAY_OF_MONTH)) });
}
catch (Exception e)
{
date_display.setText("" + cal.get(Calendar.DAY_OF_MONTH));
e.printStackTrace();
}
}
public void setTimeChangedListener(TimeWatcher listener)
{
this.mTimeWatcher = listener;
}
public void removeTimeChangedListener()
{
this.mTimeWatcher = null;
}
View.OnClickListener hour_plus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
hour_display.requestFocus();
try
{
cal.add(Calendar.HOUR_OF_DAY, 1);
sendToDisplay();
}
catch (Exception e)
{
Log.e("", e.toString());
}
}
};
View.OnClickListener hour_minus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
hour_display.requestFocus();
try
{
cal.add(Calendar.HOUR_OF_DAY, -1);
sendToDisplay();
}
catch (Exception e)
{
Log.e("", e.toString());
}
}
};
View.OnClickListener min_plus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
min_display.requestFocus();
try
{
cal.add(Calendar.MINUTE, 1);
sendToDisplay();
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
View.OnClickListener min_minus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
min_display.requestFocus();
try
{
cal.add(Calendar.MINUTE, -1);
sendToDisplay();
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
String[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug","Sep", "Oct", "Nov", "Dec" };
View.OnClickListener month_plus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try
{
cal.add(Calendar.MONTH, 1);
month_display.setText(months[cal.get(Calendar.MONTH)]);
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
changeFilter();
sendToListener();
}
catch (Exception e)
{
Log.e("", e.toString());
}
}
};
View.OnClickListener month_minus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try
{
cal.add(Calendar.MONTH, -1);
month_display.setText(months[cal.get(Calendar.MONTH)]);
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
changeFilter();
sendToListener();
}
catch (Exception e)
{
Log.e("", e.toString());
}
}
};
View.OnClickListener date_plus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try
{
date_display.requestFocus();
cal.add(Calendar.DAY_OF_MONTH, 1);
month_display.setText(months[cal.get(Calendar.MONTH)]);
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
sendToListener();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
View.OnClickListener date_minus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try {
date_display.requestFocus();
cal.add(Calendar.DAY_OF_MONTH, -1);
month_display.setText(months[cal.get(Calendar.MONTH)]);
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
sendToListener();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
View.OnClickListener year_plus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try {
year_display.requestFocus();
if (cal.get(Calendar.YEAR) >= endYear)
{
cal.set(Calendar.YEAR, startYear);
}
else
{
cal.add(Calendar.YEAR, +1);
}
month_display.setText(months[cal.get(Calendar.MONTH)]);
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
changeFilter();
sendToListener();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
View.OnClickListener year_minus_listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
try {
year_display.requestFocus();
if (cal.get(Calendar.YEAR) <= startYear) {
cal.set(Calendar.YEAR, endYear);
}
else
{
cal.add(Calendar.YEAR, -1);
}
month_display.setText(months[cal.get(Calendar.MONTH)]);
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
changeFilter();
sendToListener();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
class InputFilterMinMax implements InputFilter
{
private int min, max;
public InputFilterMinMax(int min, int max)
{
this.min = min;
this.max = max;
}
public InputFilterMinMax(String min, String max)
{
this.min = Integer.parseInt(min);
this.max = Integer.parseInt(max);
}
@Override
public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend)
{
try {
int input = Integer.parseInt(dest.toString()+ source.toString());
if (isInRange(min, max, input))
{
return null;
}
}
catch (NumberFormatException nfe)
{
}
return "";
}
private boolean isInRange(int a, int b, int c)
{
return b > a ? c >= a && c <= b : c >= b && c <= a;
}
}
public void reset()
{
cal = Calendar.getInstance();
initFilterNumericDigit();
initData();
sendToDisplay();
}
synchronized private void sendToListener()
{
if (mTimeWatcher != null)
{
mTimeWatcher.onTimeChanged(cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE), -1);
}
if (mDateWatcher != null)
{
mDateWatcher.onDateChanged(cal);
}
}
private void sendToDisplay()
{
hour_display.setText(String.valueOf(cal.get(Calendar.HOUR_OF_DAY)));
min_display.setText(String.valueOf(cal.get(Calendar.MINUTE)));
}
TimeWatcher mTimeWatcher = null;
public interface TimeWatcher
{
void onTimeChanged(int h, int m, int am_pm);
}
TextWatcher hour_watcher = new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before,int count)
{
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after)
{
}
@Override
public void afterTextChanged(Editable s)
{
try
{
if (s.toString().length() > 0)
{
cal.set(Calendar.HOUR_OF_DAY,Integer.parseInt(s.toString()));
sendToListener();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
TextWatcher min_watcher = new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before,int count)
{
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after)
{
}
@Override
public void afterTextChanged(Editable s)
{
try
{
if (s.toString().length() > 0)
{
cal.set(Calendar.MINUTE, Integer.parseInt(s.toString()));
sendToListener();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
public int getYear()
{
return Integer.parseInt(year_display.getText().toString());
}
public int getDay()
{
return Integer.parseInt(date_display.getText().toString());
}
public String getMonth()
{
return month_display.getText().toString();
}
public int getHour()
{
return Integer.parseInt(hour_display.getText().toString());
}
public int getMinute()
{
return Integer.parseInt(min_display.getText().toString());
}
public void setDateChangedListener(DateWatcher listener)
{
this.mDateWatcher = listener;
}
public void removeDateChangedListener()
{
this.mDateWatcher = null;
}
View.OnFocusChangeListener mLostFocusYear = new OnFocusChangeListener()
{
@Override
public void onFocusChange(View v, boolean hasFocus)
{
if (!hasFocus)
{
year_display.setText(String.valueOf(cal.get(Calendar.YEAR)));
}
}
};
TextWatcher date_watcher = new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before,int count)
{
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after)
{
}
@Override
public void afterTextChanged(Editable s)
{
try
{
if (s.toString().length() > 0)
{
// Log.e("", "afterTextChanged : " + s.toString());
cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(s.toString()));
month_display.setText(months[cal.get(Calendar.MONTH)]);
sendToListener();
}
}
catch (NumberFormatException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
TextWatcher year_watcher = new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before,int count)
{
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after)
{
}
@Override
public void afterTextChanged(Editable s)
{
try
{
if (s.toString().length() == 4)
{
int year = Integer.parseInt(s.toString());
if (year > endYear)
{
cal.set(Calendar.YEAR, endYear);
}
else if (year < startYear)
{
cal.set(Calendar.YEAR, startYear);
}
else
{
cal.set(Calendar.YEAR, year);
}
}
sendToListener();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
DateWatcher mDateWatcher = null;
public interface DateWatcher
{
void onDateChanged(Calendar c);
}
}
public void button_click(View view)
{
// Create the dialog
final Dialog mDateTimeDialog = new Dialog(this);
// Inflate the root layout
final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);
// Grab widget instance
final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
mDateTimePicker.setDateChangedListener(this);
// Update demo TextViews when the "OK" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.SetDateTime)).setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
mDateTimePicker.clearFocus();
// TODO Auto-generated method stub
String result_string = mDateTimePicker.getMonth() + "/" + String.valueOf(mDateTimePicker.getDay()) + "/" + String.valueOf(mDateTimePicker.getYear())+ " " + String.valueOf(mDateTimePicker.getHour()) + ":" + String.valueOf(mDateTimePicker.getMinute());
// if(mDateTimePicker.getHour() > 12) result_string = result_string + "PM";
// else result_string = result_string + "AM";
//if(result_string<)
edit_text.setText(result_string);
mDateTimeDialog.dismiss();
}
});
// Cancel the dialog when the "Cancel" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.CancelDialog)).setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
// TODO Auto-generated method stub
mDateTimeDialog.cancel();
}
});
// Reset Date and Time pickers when the "Reset" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.ResetDateTime)).setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
// TODO Auto-generated method stub
mDateTimePicker.reset();
}
});
// Setup TimePicker
// No title on the dialog window
mDateTimeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the dialog content view
mDateTimeDialog.setContentView(mDateTimeDialogView);
// Display the dialog
mDateTimeDialog.show();
}
public void onDateChanged(Calendar c)
{
Log.e("","" + c.get(Calendar.MONTH) + " " + c.get(Calendar.DAY_OF_MONTH)+ " " + c.get(Calendar.YEAR));
}`enter code here`
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/DateTimePicker"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:padding="5dip" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/month_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/month_plus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_up" />
<EditText
android:id="@+id/month_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:focusable="false"
android:gravity="center"
android:singleLine="true"
android:textColor="#C0C0C0" >
</EditText>
<Button
android:id="@+id/month_minus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/date_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/date_plus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_up" />
<EditText
android:id="@+id/date_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:inputType="number"
android:singleLine="true"
android:textColor="#C0C0C0" />
<Button
android:id="@+id/date_minus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/year_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/year_plus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_up" />
<EditText
android:id="@+id/year_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:inputType="number"
android:singleLine="true"
android:textColor="#C0C0C0" />
<Button
android:id="@+id/year_minus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/hour_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/hour_plus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_up" />
<EditText
android:id="@+id/hour_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:inputType="number"
android:singleLine="true"
android:textColor="#C0C0C0" >
</EditText>
<Button
android:id="@+id/hour_minus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/min_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/min_plus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_up" />
<EditText
android:id="@+id/min_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:inputType="number"
android:singleLine="true"
android:textColor="#C0C0C0" />
<Button
android:id="@+id/min_minus"
android:layout_width="40dp"
android:layout_height="28dp"
android:background="@drawable/image_button_down" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>`enter code here`