Android基于wheelView的自定义日期选择器

合集下载

[Android]竖直滑动选择器WheelView的实现

[Android]竖直滑动选择器WheelView的实现

[Android]竖直滑动选择器WheelView的实现以下内容为原创,转载请注明:公司项⽬中有这么⼀个需求,所以需要⾃⼰实现下。

效果类似android4.0以上原⽣的DatePicker这种。

先贴上效果图:讲下思路吧,因为这是⼀个滚动选择器,所以⾸先想到的是可以基于ListView或者ScrollView⾃定义。

刚开始我⽤的是继承ListView来实现,把滑动选择的每个item作为listview中的⼀个item,然后根据FirstVisiblePosition、LastVisiblePosition 来判断某个item是否在选中的区域,但是后来发现偶尔有时候调⽤getFirstVisiblePosition和getLastVisiblePosition的结果跟我看到的界⾯显⽰的item并不⼀致(我是在Adapter中调⽤的这两个⽅法),后来分析可能是因为我调⽤了scrollTo后没有刷新adapter的原因吧。

再后来,就打算使⽤ScrollView来实现了,其中的每个item都是⼀个View(我这⾥使⽤了TextView)。

因为这个选中框是在中间的位置,所以刚启动时第⼀个item应该需要在中间选中框显⽰,所以前⾯应该使⽤空⽩补全。

最后⼀个也是如此,后⾯也需要空⽩补全。

在滑动过程中需要实现这种场景:滑动结束后,必须且只有⼀个item完整显⽰在选择框中。

所以我们必须要监听滚动停⽌的事件,然后在滚动停⽌后判断是不是满⾜前⾯的场景,如果没有,则需要代码中实现滚动到正确位置。

但是,蛋疼的是,sdk中竟然没有提供原⽣的监听滚动停⽌的api,然后在⽹上找了很久,得到的结果是只能另辟蹊径,使⽤了⼀个⽹友的做法通过主动检测是否停⽌滚动的⽅法去实现(总觉得⽅法有点坑,额好吧但是暂时先⽤了这个⽅法)。

思路就讲到这⾥了。

使⽤⽅式:/*** Author: wangjie* Email: tiantian.china.2@* Date: 7/1/14.*/@AILayout(yout.main)public class MainActivity extends AIActivity {public static final String TAG = MainActivity.class.getSimpleName();private static final String[] PLANETS = new String[]{"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Uranus", "Neptune", "Pluto"};@AIView(R.id.main_wv)private WheelView wva;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);wva.setOffset(1);wva.setItems(Arrays.asList(PLANETS));wva.setOnWheelViewListener(new WheelView.OnWheelViewListener() {@Overridepublic void onSelected(int selectedIndex, String item) {Logger.d(TAG, "selectedIndex: " + selectedIndex + ", item: " + item);}});}@AIClick({R.id.main_show_dialog_btn})public void onClickCallbackSample(View view) {switch (view.getId()) {case R.id.main_show_dialog_btn:View outerView = LayoutInflater.from(context).inflate(yout.wheel_view, null);WheelView wv = (WheelView) outerView.findViewById(R.id.wheel_view_wv);wv.setOffset(2);wv.setItems(Arrays.asList(PLANETS));wv.setSeletion(3);wv.setOnWheelViewListener(new WheelView.OnWheelViewListener() {@Overridepublic void onSelected(int selectedIndex, String item) {Logger.d(TAG, "[Dialog]selectedIndex: " + selectedIndex + ", item: " + item);}});new AlertDialog.Builder(context).setTitle("WheelView in Dialog").setView(outerView).setPositiveButton("OK", null).show();break;}}}注意:这个Demo只是⼀个临时解决⽅案,⽐较适合选项较少的时候使⽤,⽐如选择性别、星期等。

AndroidPickerView滚动选择器的使用方法

AndroidPickerView滚动选择器的使用方法

AndroidPickerView滚动选择器的使⽤⽅法⼿机⾥设置闹钟需要选择时间,那个选择时间的控件就是滚动选择器,前⼏天⽤⼿机刷了MIUI,发现⾃带的那个时间选择器效果挺好看的,于是就⾃⼰仿写了⼀个,权当练⼿。

先来看效果:效果还⾏吧?实现思路就是⾃定义⼀个PickerView,单独滚动的是⼀个PickerView,显然上图中有分和秒的选择所以在布局⾥⽤了两个PickerView。

由于这⾥不涉及到text的点击事件,所以只需要继承View就⾏了,直接把text⽤canvas画上去。

PickerView的实现的主要难点:难点1:字体随距离的渐变。

可以看到,text随离中⼼位置的距离变化⽽变化,这⾥变化的是透明度alpha和字体⼤⼩TexSize,这两个值我都设置了Max和Min值,通过其与中⼼点的距离计算scale。

我⽤的是变化曲线是抛物线scale=1-ax^2(x<=Height/4),scale = 0(x>Height/4),a=(4/Height)^2。

x就是距离View中⼼的偏移量。

⽤图⽚表⽰如下:难点2:text的居中。

绘制text的时候不仅要使其在x⽅向上居中,还要在y⽅向上居中,在x⽅向上⽐较简单,设置Paint的Align为Align.CENTER就⾏了,但是y⽅向上很蛋疼,需要计算text的baseline。

难点3:循环滚动。

为了解决循环滚动的问题我把存放text的List从中间往上下摊开,通过不断地moveHeadToTail和moveTailToHead使选中的text始终是list的中间position的值。

以上就是⼏个难点,了解了之后可以来看PickerView的代码了:package com.jingchen.timerpicker;import java.util.ArrayList;import java.util.List;import java.util.Timer;import java.util.TimerTask;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Paint.Align;import android.graphics.Paint.FontMetricsInt;import android.graphics.Paint.Style;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;/*** 滚动选择器** @author chenjing**/public class PickerView extends View{public static final String TAG = "PickerView";/*** text之间间距和minTextSize之⽐*/public static final float MARGIN_ALPHA = 2.8f;/*** ⾃动回滚到中间的速度*/public static final float SPEED = 2;private List<String> mDataList;/*** 选中的位置,这个位置是mDataList的中⼼位置,⼀直不变private int mCurrentSelected;private Paint mPaint;private float mMaxTextSize = 80;private float mMinTextSize = 40;private float mMaxTextAlpha = 255;private float mMinTextAlpha = 120;private int mColorText = 0x333333;private int mViewHeight;private int mViewWidth;private float mLastDownY;/*** 滑动的距离*/private float mMoveLen = 0;private boolean isInit = false;private onSelectListener mSelectListener;private Timer timer;private MyTimerTask mTask;Handler updateHandler = new Handler(){@Overridepublic void handleMessage(Message msg){if (Math.abs(mMoveLen) < SPEED){mMoveLen = 0;if (mTask != null){mTask.cancel();mTask = null;performSelect();}} else// 这⾥mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚 mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED;invalidate();}};public PickerView(Context context){super(context);init();}public PickerView(Context context, AttributeSet attrs){super(context, attrs);init();}public void setOnSelectListener(onSelectListener listener){mSelectListener = listener;}private void performSelect(){if (mSelectListener != null)mSelectListener.onSelect(mDataList.get(mCurrentSelected));}public void setData(List<String> datas){mDataList = datas;mCurrentSelected = datas.size() / 2;invalidate();public void setSelected(int selected){mCurrentSelected = selected;}private void moveHeadToTail(){String head = mDataList.get(0);mDataList.remove(0);mDataList.add(head);}private void moveTailToHead(){String tail = mDataList.get(mDataList.size() - 1);mDataList.remove(mDataList.size() - 1);mDataList.add(0, tail);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);mViewHeight = getMeasuredHeight();mViewWidth = getMeasuredWidth();// 按照View的⾼度计算字体⼤⼩mMaxTextSize = mViewHeight / 4.0f;mMinTextSize = mMaxTextSize / 2f;isInit = true;invalidate();}private void init(){timer = new Timer();mDataList = new ArrayList<String>();mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setStyle(Style.FILL);mPaint.setTextAlign(Align.CENTER);mPaint.setColor(mColorText);}@Overrideprotected void onDraw(Canvas canvas){super.onDraw(canvas);// 根据index绘制viewif (isInit)drawData(canvas);}private void drawData(Canvas canvas){// 先绘制选中的text再往上往下绘制其余的textfloat scale = parabola(mViewHeight / 4.0f, mMoveLen);float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;mPaint.setTextSize(size);mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha)); // text居中绘制,注意baseline的计算才能达到居中,y值是text中⼼坐标float x = (float) (mViewWidth / 2.0);float y = (float) (mViewHeight / 2.0 + mMoveLen);FontMetricsInt fmi = mPaint.getFontMetricsInt();float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));canvas.drawText(mDataList.get(mCurrentSelected), x, baseline, mPaint);// 绘制上⽅datafor (int i = 1; (mCurrentSelected - i) >= 0; i++){drawOtherText(canvas, i, -1);}// 绘制下⽅datafor (int i = 1; (mCurrentSelected + i) < mDataList.size(); i++){drawOtherText(canvas, i, 1);}/*** @param canvas* @param position* 距离mCurrentSelected的差值* @param type* 1表⽰向下绘制,-1表⽰向上绘制*/private void drawOtherText(Canvas canvas, int position, int type){float d = (float) (MARGIN_ALPHA * mMinTextSize * position + type* mMoveLen);float scale = parabola(mViewHeight / 4.0f, d);float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;mPaint.setTextSize(size);mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha)); float y = (float) (mViewHeight / 2.0 + type * d);FontMetricsInt fmi = mPaint.getFontMetricsInt();float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));canvas.drawText(mDataList.get(mCurrentSelected + type * position),(float) (mViewWidth / 2.0), baseline, mPaint);}/*** 抛物线** @param zero* 零点坐标* @param x* 偏移量* @return scale*/private float parabola(float zero, float x){float f = (float) (1 - Math.pow(x / zero, 2));return f < 0 ? 0 : f;}@Overridepublic boolean onTouchEvent(MotionEvent event){switch (event.getActionMasked()){case MotionEvent.ACTION_DOWN:doDown(event);break;case MotionEvent.ACTION_MOVE:doMove(event);break;case MotionEvent.ACTION_UP:doUp(event);break;}return true;}private void doDown(MotionEvent event){if (mTask != null){mTask.cancel();mTask = null;}mLastDownY = event.getY();}private void doMove(MotionEvent event){mMoveLen += (event.getY() - mLastDownY);if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2){// 往下滑超过离开距离moveTailToHead();mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;} else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2){// 往上滑超过离开距离moveHeadToTail();mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;}mLastDownY = event.getY();invalidate();}private void doUp(MotionEvent event){// 抬起⼿后mCurrentSelected的位置由当前位置move到中间选中位置if (Math.abs(mMoveLen) < 0.0001){mMoveLen = 0;return;}if (mTask != null){mTask.cancel();mTask = null;}mTask = new MyTimerTask(updateHandler);timer.schedule(mTask, 0, 10);}class MyTimerTask extends TimerTask{Handler handler;public MyTimerTask(Handler handler){this.handler = handler;}@Overridepublic void run(){handler.sendMessage(handler.obtainMessage());}}public interface onSelectListener{void onSelect(String text);}}代码⾥的注释都写的很清楚了。

Android日期时间选择器实现以及自定义大小

Android日期时间选择器实现以及自定义大小

Android⽇期时间选择器实现以及⾃定义⼤⼩本⽂主要讲两个内容:1.如何将DatePicker和TimePicker放在⼀个dialog⾥⾯;2.改变他们的宽度;问题1:其实现思路就是⾃定义⼀个Dialog,然后往⾥⾯同时放⼊DatePicker和TimePicker,直接贴代码:date_time_picker.xml:<LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal" ><!-- <DatePickerandroid:id="@+id/new_act_date_picker"android:layout_width="0dip"android:layout_height="wrap_content"android:layout_weight="0.6"android:calendarViewShown="false" /><TimePickerandroid:id="@+id/new_act_time_picker"android:layout_width="0dip"android:layout_height="wrap_content"android:layout_weight="0.3"/> --><DatePickerandroid:id="@+id/new_act_date_picker"android:layout_width="wrap_content"android:layout_height="wrap_content"android:calendarViewShown="false" /><TimePickerandroid:id="@+id/new_act_time_picker"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>然后在需要显⽰⽇期时间选择器的地⽅(⼀般是⼀个onClickListener中)实例化dialog:DemoActivity.javaarriveAtBtn.setOnClickListener(new View.OnClickListener(){@SuppressLint("NewApi")@Overridepublic void onClick(View v) {View view = View.inflate(getApplicationContext(), yout.date_time_picker, null);final DatePicker datePicker = (DatePicker)view.findViewById(R.id.new_act_date_picker);final TimePicker timePicker = (TimePicker)view.findViewById(R.id.new_act_time_picker);// Init DatePickerint year;int month;int day;if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) {// Use the current date as the default date in the pickerfinal Calendar c = Calendar.getInstance();year = c.get(Calendar.YEAR);month = c.get(Calendar.MONTH);day = c.get(Calendar.DAY_OF_MONTH);} else {year = NewActActivity.arrive_year;month = NewActActivity.arrive_month;day = NewActActivity.arrive_day;}datePicker.init(year, month, day, null);// Init TimePickerint hour;int minute;if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) {// Use the current time as the default values for the pickerfinal Calendar c = Calendar.getInstance();hour = c.get(Calendar.HOUR_OF_DAY);minute = c.get(Calendar.MINUTE);} else {hour = NewActActivity.arrive_hour;minute = NewActActivity.arrive_min;}timePicker.setIs24HourView(true);timePicker.setCurrentHour(hour);timePicker.setCurrentMinute(minute);// Build DateTimeDialogAlertDialog.Builder builder = new AlertDialog.Builder(NewActActivity.this);builder.setView(view);builder.setTitle(R.string.new_act_date_time_picker_title);builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {arrive_year = datePicker.getYear();arrive_month = datePicker.getMonth();arrive_day = datePicker.getDayOfMonth();String dateStr = DateUtil.formatDate(arrive_year, arrive_month, arrive_day);arriveDateBtn.setText(dateStr);arrive_hour = timePicker.getCurrentHour();arrive_min = timePicker.getCurrentMinute();String timeStr = DateUtil.formatTime(arrive_hour, arrive_min);arriveTimeBtn.setText(timeStr);}});builder.show();}});这样就可以实现⽇期时间选择器了,这⾥就有点layout上的⼩问题,你是需要datepicker和timepicker⽔平排列还是竖直排列,竖直排列是没问题的:下⾯给出两个数值排列的效果图:(1)DatePicker控件中设置android:calendarViewShown="false" 时的效果图:(2)(1)DatePicker控件中设置android:spinnersShown="false" 时的效果图:当然,如果你android:calendarViewShown和android:spinnersShown都不设置为false的话,会同时显⽰⽇历和滚动条样式,我想⼀般不会有⼈想要这样的视图吧。

android2.1 自定义日历控件

android2.1 自定义日历控件

package com.threeeyes.util;import java.util.Calendar;import com.threeeyes.activity.R;import android.R.color;import android.app.Activity;import android.content.Context;import android.graphics.Color;import android.os.Bundle;import android.util.Log;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageButton;import android.widget.LinearLayout;import android.widget.TableLayout;import android.widget.TableRow;import android.widget.TextView;import android.widget.Toast;import youtParams;public class DateTime extends LinearLayout {TableLayout table;TextView showDateTxt;TextView btnpre;TextView btnnext;TextView nowDate;int year;int month; // 0,1,..,,11int srcday; // 初始日int srcyear; // 初始年int srcmonth; // 初始月String[] weeks = { "周日", "周一", "周二", "周三", "周四", "周五", "周六" };View preSelectedView = null; // 前一个选中的日期Context ct;DateCallBack callBack;int weekTitleColor = 0xFFFF0000;int dayColor = 0xFFFF0000;int titleColor = Color.BLACK;int selectedColor = Color.TRANSPARENT;boolean init = false; // 初始化标志int colWidth = 30; // 单元格宽度int rowHeight = 0; // 单元格高度int textSize = 12;LinearLayout dayLayOut;public DateTime(Context context, final int year1, final int month1, int day1) { super(context);ct = context;this.srcmonth=month1;this.srcyear=year1;setOrientation(LinearLayout.VERTICAL);setLayoutParams(new LayoutParams(youtParams.WRAP_CONTENT,youtParams.WRAP_CONTENT));setBackgroundColor(Color.GRAY);LinearLayout titleLayOut = new LinearLayout(ct);titleLayOut.setOrientation(LinearLayout.HORIZONTAL);titleLayOut.setGravity(Gravity.CENTER_HORIZONTAL);addView(titleLayOut);table = new TableLayout(ct);addView(table);showDateTxt = new TextView(ct);youtParams la = new youtParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);la.rightMargin = 20;la.leftMargin = 20;showDateTxt.setLayoutParams(la);showDateTxt.setTextSize(textSize);this.year = year1;if (month1 < 1 || month1 > 12)this.month = 0;elsethis.month = month1 - 1;if (day1 < 1 || day1 > 31)this.srcday = 1;elsethis.srcday = day1;showDateTxt.setText(String.valueOf(year1) + "年" + String.valueOf(month1)); showDateTxt.setTextColor(titleColor);btnpre = new TextView(ct);btnpre.setTextColor(titleColor);btnpre.setText("上月");btnpre.setTextSize(textSize);btnnext = new TextView(ct);btnnext.setTextColor(titleColor);btnnext.setText("下月");btnnext.setTextSize(textSize);nowDate = new TextView(ct);nowDate.setTextColor(titleColor);nowDate.setText("今天");nowDate.setTextSize(textSize);nowDate.setGravity(Gravity.CENTER_HORIZONTAL);dayLayOut = new LinearLayout(ct);dayLayOut.setOrientation(LinearLayout.VERTICAL);dayLayOut.setGravity(Gravity.CENTER_VERTICAL);dayLayOut.addView(showDateTxt);dayLayOut.addView(nowDate);titleLayOut.addView(btnpre);titleLayOut.addView(dayLayOut);titleLayOut.addView(btnnext);nowDate.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubyear = srcyear;month = srcmonth-1;showDateTxt.setText(String.valueOf(year) + "年"+ String.valueOf(month + 1) + "月");loadDate(1,1+5);}});btnnext.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (preSelectedView != null)preSelectedView.setBackgroundColor(color.transparent);nextMonth();showDateTxt.setText(String.valueOf(year) + "年"+ String.valueOf(month + 1) + "月");loadDate(1, 1 + 5);}});btnpre.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubpreMonth();showDateTxt.setText(String.valueOf(year) + "年"+ String.valueOf(month + 1) + "月");loadDate(1, 1 + 5);}});}public void setPre_Next_BackGround(int preRes, int nextPre) {btnpre.setBackgroundResource(preRes);btnnext.setBackgroundResource(nextPre);btnpre.setText("");btnnext.setText("");}public void setNowDateBackGround(int res) {dayLayOut.setBackgroundResource(res);}/*** 初始化日期** @param titleCoclor* 标题颜色* @param weekTitleColor* 星期颜色* @param dayColor* 日期颜色*/public void initDate(int titleCoclor, int weekTitleColor, int dayColor, int selectedColor) {if (!init) {this.weekTitleColor = weekTitleColor;this.dayColor = dayColor;this.titleColor = titleCoclor;showDateTxt.setTextColor(titleCoclor);btnpre.setTextColor(titleCoclor);btnnext.setTextColor(titleCoclor);this.selectedColor = selectedColor;generateDate();}}/*** 初始化日期颜色默认*/public void initDate() {if (!init) {generateDate();}}/*** 以"周日","周一","周二","周三","周四","周五","周六"为顺序** @param weekdays*/public void setWeekTitle(String[] weekdays) {if (weekdays != null && weekdays.length > 0 && weekdays.length == 7) this.weeks = weekdays;}public int maxDay() {Calendar time = Calendar.getInstance();Log.v("", time.toString());time.clear();time.set(Calendar.YEAR, year);time.set(Calendar.MONTH, month);int day = time.getActualMaximum(Calendar.DAY_OF_MONTH);// 本月份的天数return day;}public int nowWeekDay() {Calendar time = Calendar.getInstance();Log.v("", time.toString());time.clear();time.set(Calendar.YEAR, year);time.set(Calendar.MONTH, month);time.set(Calendar.DATE, 1);int weekday = time.get(Calendar.DAY_OF_WEEK);if (weekday == 7)return 0;elsereturn weekday - 1;}public void generateDate() {youtParams params = new youtParams(youtParams.WRAP_CONTENT,youtParams.WRAP_CONTENT);TableRow row2 = new TableRow(ct);row2.setPadding(0, 2, 0, 0);row2.setGravity(Gravity.CENTER_HORIZONTAL);for (int i = 0; i < 7; i++) {TextView col1 = new TextView(ct);col1.setMinWidth(colWidth);col1.setMaxWidth(colWidth);if (rowHeight > 0)col1.setMinHeight(rowHeight);col1.setTextColor(weekTitleColor);col1.setText(weeks[i]);col1.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);col1.setTextSize(textSize);row2.addView(col1); // 添加列}table.addView(row2);int weekday = nowWeekDay();int maxday = maxDay();Log.v("date----", weekday + "-----------" + maxday);int count = 0;for (int i = 0; i < 5; i++) { // 添加6行TableRow row = new TableRow(ct);row.setPadding(0, 2, 0, 2);row.setGravity(Gravity.CENTER_HORIZONTAL);row.setLayoutParams(params);// row.setBackgroundColor(0xFF00FF00);for (int j = 0; j < 7; j++) { // 添加1列TextView col = new TextView(ct);col.setTextColor(dayColor);col.setBackgroundColor(color.transparent);col.setTextSize(textSize);if (rowHeight > 0)col.setMinHeight(rowHeight);if (i == 0) {if (weekday <= j) {count++;col.setText(String.valueOf(count));}} else {if (count < maxday) {count++;col.setText(String.valueOf(count));}}col.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (((TextView) v).getText().toString().length() > 0) {if (preSelectedView != null) {preSelectedView.setBackgroundColor(color.transparent);}preSelectedView = v;v.setBackgroundColor(selectedColor);callBack.execute(v, year + "", (month + 1) + "",((TextView) v).getText().toString());}}});if (srcday == count) {col.setBackgroundColor(selectedColor);this.preSelectedView = col;}col.setGravity(Gravity.CENTER_HORIZONTAL| Gravity.CENTER_VERTICAL);row.addView(col); // 添加列}table.addView(row);// 添加行}}public void nextMonth() {if (month == 11) {year++;month = 0;} else {month++;}}public void preMonth() {if (month == 0) {year--;month = 11;} else {month--;}}public void loadDate(int startIndex, int endIndex) {int weekday = nowWeekDay();int maxday = maxDay();Log.v("date----", weekday + "-----------" + maxday);int count = 0;for (int i = startIndex; i < endIndex; i++) {TableRow row = (TableRow) table.getChildAt(i);for (int j = 0; j < 7; j++) {TextView col = (TextView) row.getChildAt(j);if (i == startIndex) {if (weekday <= j) {count++;col.setText(String.valueOf(count));if (srcday == count) {col.setBackgroundColor(selectedColor);this.preSelectedView = col;}} else {col.setText("");}} else {if (count < maxday) {count++;col.setText(String.valueOf(count));} else {col.setText("");}}if (srcday == count) {col.setBackgroundColor(selectedColor);if (this.preSelectedView != col)this.preSelectedView.setBackgroundColor(color.transparent);this.preSelectedView = col;}}}}/*** 回调函数** @author Acer**/public interface DateCallBack {public void execute(View v, String year, String month, String day);}public void setCallBack(DateCallBack callBack) {this.callBack = callBack;}/*** 设置单元格的宽度,高度** @param colWidth* 单元格宽度* @param rowHeight* 单元格高度* @param textSize1* 文字大小*/public void setWidthHeightTextSize(int colWidth, int rowHeight,int textSize1) {if (colWidth > 0)this.colWidth = colWidth;this.rowHeight = rowHeight;this.textSize = textSize1;btnpre.setTextSize(textSize1);btnnext.setTextSize(textSize1);showDateTxt.setTextSize(textSize1);}}。

Android自定义控件之日期选择控件使用详解

Android自定义控件之日期选择控件使用详解

Android⾃定义控件之⽇期选择控件使⽤详解Android⽇期选择控件效果如下:调⽤的代码:@OnClick(R.id.btn0)public void btn0() {final AlertDialog dialog = new AlertDialog.Builder(context).create();dialog.show();Window window = dialog.getWindow();window.setContentView(yout.dialog_change_date);window.setBackgroundDrawable(new ColorDrawable(0x00000000)); // 处理5.0以上对话框的⽩边问题window.setGravity(Gravity.BOTTOM);final DatePickerView datePickerView = (DatePickerView) window.findViewById(R.id.datePickerView);//打开页⾯时需要选中的⽇期 TODOdatePickerView.setDate(2015, 5, 11);// datePickerView.setDate(birthdayArray[0], birthdayArray[1], birthdayArray[2]);final int[] birthdayArray = new int[3];datePickerView.addOnSelectedChangingListener(new DatePickerView.OnSelectedChangedListener() {@Overridepublic void OnSelectedChanged(int[] oldValue, int[] newValue) {birthdayArray[0] = newValue[0];birthdayArray[1] = newValue[1];birthdayArray[2] = newValue[2];}});window.findViewById(Cancel).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {dialog.dismiss();}});window.findViewById(OK).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {dialog.dismiss();btn0.setText(birthdayArray[0] + "年" + birthdayArray[1] + "⽉" + birthdayArray[2] + "⽇"); }});}1.WheelView 源码(有修改)2.xml布局⽂件<?xml version="1.0" encoding="utf-8"?><!--widget_date_picker.xml--><!--注意修改页⾯⾃定义控件的包名--><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><de.bvb.rxdemo.widget.DateSelectWidget.wheelview.WheelViewandroid:id="@+id/wheelViewYear"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"/><de.bvb.rxdemo.widget.DateSelectWidget.wheelview.WheelViewandroid:id="@+id/wheelViewMonth"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"/><de.bvb.rxdemo.widget.DateSelectWidget.wheelview.WheelViewandroid:id="@+id/wheelViewDay"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"/></LinearLayout><?xml version="1.0" encoding="utf-8"?><!--dialog_change_date.xml--><!--注意修改页⾯⾃定义控件的包名--><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/transparent"android:gravity="bottom"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@android:color/white"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="48dp"android:orientation="horizontal"><TextViewandroid:id="@+id/tvCancel"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#F9F9F9"android:gravity="center"android:text="取消"android:textColor="#43AAFC"/><Viewandroid:layout_width="1px"android:layout_height="match_parent"android:background="#D7D7D7"/><TextViewandroid:id="@+id/tvOK"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#F9F9F9"android:gravity="center"android:text="确定"android:textColor="#43AAFC"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="#D7D7D7"/><de.bvb.rxdemo.widget.DateSelectWidget.DatePickerViewandroid:id="@+id/datePickerView"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout></LinearLayout>3.java⽂件package de.bvb.rxdemo.widget.DateSelectWidget;import android.content.Context;import android.util.AttributeSet;import youtInflater;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;import java.util.ArrayList;import de.bvb.rxdemo.R;import de.bvb.rxdemo.widget.DateSelectWidget.wheelview.OnWheelChangedListener;import de.bvb.rxdemo.widget.DateSelectWidget.wheelview.OnWheelScrollListener;import de.bvb.rxdemo.widget.DateSelectWidget.wheelview.WheelView;import de.bvb.rxdemo.widget.DateSelectWidget.wheelview.adapter.AbstractWheelTextAdapter1; public class DatePickerView extends LinearLayout {private static final int YEAR_MIN = 1950;private static final int YEAR_MAX = 2020;private int year = YEAR_MIN;private int month = 1;private int day = 1;private ArrayList<Integer> yearList = new ArrayList<>(YEAR_MAX - YEAR_MIN + 1);private ArrayList<Integer> monthList = new ArrayList<>(12);private ArrayList<Integer> dayList = new ArrayList<>(31);private DateTextAdapter yearAdapter;private DateTextAdapter monthAdapter;private DateTextAdapter dayAdapter;private Context context;private WheelView wheelViewYear;private WheelView wheelViewMonth;private WheelView wheelViewDay;public DatePickerView(Context context) {this(context, null);}public DatePickerView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public DatePickerView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);this.context = context;init();}private void init() {for (int i = YEAR_MIN; i < YEAR_MAX + 1; i++) {yearList.add(i);}for (int i = 1; i < 13; i++) {monthList.add(i);}for (int i = 1; i < 32; i++) {dayList.add(i);}LayoutInflater.from(context).inflate(yout.widget_date_picker, this);// View.inflate(context, yout.widget_date_picker, this);wheelViewYear = (WheelView) findViewById(R.id.wheelViewYear);wheelViewMonth = (WheelView) findViewById(R.id.wheelViewMonth);wheelViewDay = (WheelView) findViewById(R.id.wheelViewDay);wheelViewYear.setCyclic(true);// 可循环滚动wheelViewMonth.setCyclic(true);// 可循环滚动wheelViewDay.setCyclic(true);// 可循环滚动yearAdapter = new DateTextAdapter(context);monthAdapter = new DateTextAdapter(context);dayAdapter = new DateTextAdapter(context);yearAdapter.setList(yearList);monthAdapter.setList(monthList);dayAdapter.setList(dayList);wheelViewYear.setViewAdapter(yearAdapter);wheelViewMonth.setViewAdapter(monthAdapter);wheelViewDay.setViewAdapter(dayAdapter);wheelViewYear.addChangingListener(new OnWheelChangedListener() {@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {year = YEAR_MIN + newValue;int days = calcDay(year, month); // days=28dayList = getDayList(days);dayAdapter.setList(dayList);if (day > days) {dayAdapter.currentIndex = days - 1;wheelViewDay.setCurrentItem(dayAdapter.currentIndex);} else {dayAdapter.currentIndex = day - 1; // day = 30}if (onSelectedChangedListener != null) {onSelectedChangedListener.OnSelectedChanged(parseInt2Array(YEAR_MIN + oldValue, month, day), getSelectDate()); }}});wheelViewMonth.addChangingListener(new OnWheelChangedListener() {@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {month = 1 + newValue;int days = calcDay(year, month); // days=28dayList = getDayList(days);dayAdapter.setList(dayList);if (day > days) {dayAdapter.currentIndex = days - 1;wheelViewDay.setCurrentItem(dayAdapter.currentIndex);} else {dayAdapter.currentIndex = day - 1; // day = 30}if (onSelectedChangedListener != null) {onSelectedChangedListener.OnSelectedChanged(parseInt2Array(year, 1 + oldValue, day), getSelectDate()); }}});wheelViewDay.addChangingListener(new OnWheelChangedListener() {@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {day = 1 + newValue;if (onSelectedChangedListener != null) {onSelectedChangedListener.OnSelectedChanged(parseInt2Array(year, month, oldValue + 1), getSelectDate()); }}});wheelViewYear.addScrollingListener(onWheelScrollListener);wheelViewMonth.addScrollingListener(onWheelScrollListener);wheelViewDay.addScrollingListener(onWheelScrollListener);}OnWheelScrollListener onWheelScrollListener = new OnWheelScrollListener() {@Overridepublic void onScrollingStarted(WheelView wheel) {}@Overridepublic void onScrollingFinished(WheelView wheel) {setTextViewStyle();}};private void setTextViewStyle() {setTextViewSize(year + "", yearAdapter);setTextViewSize(month + "", monthAdapter);setTextViewSize(day + "", dayAdapter);}private void setTextViewSize(String currentItemText, AbstractWheelTextAdapter1 adapter) {ArrayList<View> arrayList = adapter.getTextViews();int size = arrayList.size();String currentText;TextView textView;boolean current;for (int i = 0; i < size; i++) {textView = (TextView) arrayList.get(i);currentText = textView.getText().toString();current = currentItemText.equals(currentText);textView.setTextColor(current ? adapter.selected_text_color : adapter.un_selected_text_color);textView.setTextSize(current ? adapter.selected_text_size : adapter.un_selected_text_size);}}/*** 设置控件的初始值** @param year* @param month* @param day*/public void setDate(int year, int month, int day) {//验证合法性if (year > YEAR_MAX || year < YEAR_MIN) {year = YEAR_MIN;// throw new RuntimeException("年份必须在[" + YEAR_MIN + "," + YEAR_MAX + "]之间");}if (month > 12 || month < 1) {month = 1;// throw new RuntimeException("⽉份份必须在[" + 1 + "," + 12 + "]之间");}final int days = calcDay(year, month);if (day > days || day < 1) {day = 1;// throw new RuntimeException("⽇期份必须在[" + 1 + "," + days + "]之间");}this.year = year;this.month = month;this.day = day;yearAdapter.currentIndex = DatePickerView.this.year - YEAR_MIN;monthAdapter.currentIndex = DatePickerView.this.month - 1;dayAdapter.currentIndex = DatePickerView.this.day - 1;wheelViewYear.setCurrentItem(yearAdapter.currentIndex);wheelViewMonth.setCurrentItem(monthAdapter.currentIndex);wheelViewDay.setCurrentItem(dayAdapter.currentIndex);}public void addOnSelectedChangingListener(OnSelectedChangedListener onSelectedChangedListener) { this.onSelectedChangedListener = onSelectedChangedListener;}private OnSelectedChangedListener onSelectedChangedListener;public interface OnSelectedChangedListener {void OnSelectedChanged(int[] oldValue, int[] newValue);}private int[] parseInt2Array(int year, int month, int day) {return new int[]{year, month, day};}private int[] getSelectDate() {return new int[]{year, month, day};}private ArrayList<Integer> getDayList(int days) {if (days <= 0) {return null;}ArrayList<Integer> list = new ArrayList(days);for (int i = 1; i < days + 1; i++) {list.add(i);}return list;}private int calcDay(int year, int month) {int days = 0;switch (month) {case 1:case 3:case 5:case 7:case 8:case 10:case 12:days = 31;break;case 4:case 6:case 9:case 11:days = 30;break;case 2:days = (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) ? 29 : 28;break;}return days;}private class DateTextAdapter extends AbstractWheelTextAdapter1 {ArrayList<Integer> list;public DateTextAdapter(Context context) {super(context, yout.simple_list_item_1);// super(context, yout.item_birth_year);// setItemTextResource(R.id.tempValue);// item_birth_year.xml 内容如下// <?xml version="1.0" encoding="utf-8"?>// <LinearLayout xmlns:android="/apk/res/android"// android:layout_width="match_parent"// android:layout_height="35dip"// android:gravity="center"// android:orientation="horizontal">// <TextView// android:id="@+id/tempValue"// android:layout_width="match_parent"// android:layout_height="match_parent"// android:gravity="center"// android:textColor="#ffff0000"/>// </LinearLayout>}public void setList(ArrayList<Integer> list) {this.list = list;notifyDataChangedEvent();}@Overrideprotected CharSequence getItemText(int index) {return list == null ? "" : String.valueOf(list.get(index));}@Overridepublic int getItemsCount() {return list == null ? 0 : list.size();}}}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

android开发时间选择器TimePicker的使用

android开发时间选择器TimePicker的使用

android开发时间选择器TimePicker的使⽤前⾔ 我知道现在github上有很多功能强⼤的各⾊选择器,但是Android其实是⾃带⼀些时间选择器的。

在不需要太复杂的ui开发下可以选择使⽤这些系统⾃带的。

android系统⾃带时间控件:DatePicker ⽇期显⽰控件DatePickerDialog ⽇期对话框控件TimePicker 时间显⽰控件TimePickerDialog 时间对话框控件讲解TimePicker选择器的⼀些⾃定义设置⾸先是布局的创建:<TimePickerandroid:id="@+id/timepicker"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:background="#ffffff"/>设置TimePicker选择器风格TimePicker 本⾝⾃带两种风格,都可以在xml中设置,⼀种是android:timePickerMode="clock"另⼀种是:android:timePickerMode="spinner"TimePicker的显⽰规模⼤⼩设置android:scaleX="2"android:scaleY="2"效果:TimePicker的数据回调mTimepicker = (TimePicker) inflate.findViewById(R.id.timepicker);mTimepicker.setDescendantFocusability(TimePicker.FOCUS_BLOCK_DESCENDANTS); //设置点击事件不弹键盘mTimepicker.setIs24HourView(true); //设置时间显⽰为24⼩时mTimepicker.setHour(8); //设置当前⼩时mTimepicker.setMinute(10); //设置当前分(0-59)mTimepicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { //获取当前选择的时间@Overridepublic void onTimeChanged(TimePicker view, int hourOfDay, int minute) {}});利⽤反射修改⼀些选择器的字体效果与背景颜⾊需要⽤到反射的⽅法了,⽐如更改分割线的样式,设置起始截⽌时间等:⾸先我们要通过反射获取TimePicker源码⾥hour和minute的id:Resources systemResources = Resources.getSystem();int hourNumberPickerId = systemResources.getIdentifier("hour", "id", "android");int minuteNumberPickerId = systemResources.getIdentifier("minute", "id", "android");然后⽤我们定义的TimePicker来获取这个id并转换成hour和minute对应的NumberPicker: NumberPicker hourNumberPicker = (NumberPicker) mTimepicker.findViewById(hourNumberPickerId); NumberPicker minuteNumberPicker = (NumberPicker) mTimepicker.findViewById(minuteNumberPickerId);通过获取到的hourNumberPicker和minuteNumberPicker我们可以先进⾏TimePicker的时间限制:hourNumberPicker.setMinValue(8); //设置最⼩hourhourNumberPicker.setMaxValue(12); //设置最⼤hourminuteNumberPicker .setMinValue(0); //设置最⼩minuteminuteNumberPicker .setMaxValue(30); //设置最⼤minute修改滚动条背景颜⾊hourNumberPicker.setBackgroundColor(getResources().getColor(R.color.colorBlue));// 修改背景颜⾊效果图:隐藏冒号⽤最暴⼒的⽅式隐藏滚动条的冒号,就是直接找ChildAtViewGroup view = (ViewGroup) mTimepicker.getChildAt(0);ViewGroup view2 = (ViewGroup) view.getChildAt(1);view2.getChildAt(1).setVisibility(View.GONE);禁⽌键盘输⼊mTimePicker.setDescendantFocusability(TimePicker.FOCUS_BLOCK_DESCENDANTS);TimePicker分割线的颜⾊和⾼度private void setNumberPickerDivider(NumberPicker numberPicker) {NumberPicker picker = numberPicker;Field[] pickerFields = NumberPicker.class.getDeclaredFields();for (Field pf : pickerFields) {if (pf.getName().equals("mSelectionDivider")) { //设置颜⾊pf.setAccessible(true);ColorDrawable colorDrawable = new ColorDrawable(ContextCompat.getColor(this, R.color.colortime)); //选择⾃⼰喜欢的颜⾊try {pf.set(numberPicker, colorDrawable);} catch (IllegalAccessException e) {e.printStackTrace();}}if (pf.getName().equals("mSelectionDividerHeight")) { //设置⾼度pf.setAccessible(true);try {int result = 3; //要设置的⾼度pf.set(picker, result);} catch (Exception e) {e.printStackTrace();}break;}picker.invalidate();}}。

8 Android基本组件之常用widget组件介绍(日期选择器,时间选择器,滚动视图,进度条,拖动条,评分组件)

8 Android基本组件之常用widget组件介绍(日期选择器,时间选择器,滚动视图,进度条,拖动条,评分组件)

© 2006, ZTE Corporation. All rights reserved.
日期选择器(DatePicker) 日期选择器(DatePicker)介绍与应用
在单击按钮后,会启动一个新的DatePickerActivity,所以这里我们 在单击按钮后,会启动一个新的DatePickerActivity,所以这里我们 DatePickerActivity, 应该创建一个新的DatePickerActivity.java文件。实现代码如下: DatePickerActivity.java文件 应该创建一个新的DatePickerActivity.java文件。实现代码如下: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTitle("哥就是数日子的日期选择器 哥就是数日子的日期选择器..."); 哥就是数日子的日期选择器 setContentView(yout.date_picker); DatePicker dp = (DatePicker)this.findViewById(R.id.date_picker); dp.init(2010, 5, 19, null); 的文件, 在上面代码我们可以看到, 在上面代码我们可以看到,调用了一个date_picker.xml的文件,所 我们要设计一下显示的多选框的样式,对应设计代码如下: 以,我们要设计一下显示的多选框的样式,对应设计代码如下: 代码见mouse_widget mouse_widget中的 .xml文件 文件。 代码见mouse_widget中的date_picker.xml文件。 接着在AndroidManifest.xml中添加如下代码: 接着在AndroidManifest.xml中添加如下代码: AndroidManifest.xml中添加如下代码 <activity android:name="DatePickerActivity"></activity>

Android自定义View(RollWeekView-炫酷的星期日期选择控件)

Android自定义View(RollWeekView-炫酷的星期日期选择控件)

Android自定义View(RollWeekView-炫酷的星期日期选择控件)一次展示一个星期的5天,中间放大的为当前选中的;如果点击了其中一个日期,比如星期五,那么整体向左滑动,并将星期五慢慢放大,星期三慢慢缩小,星期六和星期天就展示出来了;如果继续点击星期六,那么照样是整体向左滑动一个单位,星期日右边就需要塞进一个星期一。

就是一个无限循环的过程,中间选中的需要展示当天的日期。

1、分析最开始,我想到在LinearLayout中依次排开7个子控件(星期几),当点击之后,把所有的子控件通过动画移动相应的偏移量,但是,如果移动后就会出现空位的情况(周一的左边和周日的右边没有了),所以这种方式可是可以,但是要解决无限循环空位的情况。

于是就想到能不能多添加几个子控件作为空位替补?这个方法肯定能实现,但是究竟需要多少个替补呢?这些替补应该放在什么位置呢?当前展示的5个子控件中,如果点击最左边或者最右边,这样的偏移量是最大的,需要便宜两个子控件单位,所以左边和右边最多个需要2个替补就行了,算起来也不多,一共才9个(当前展示5个,左边隐藏替补2个,右边隐藏替补2个)。

在点击之前,先将替补位置设置好,当点击之后,所有子控件执行偏移动画(不可能出现空位,最多偏移2位),动画结束之后,再重新为隐藏的4个替补分配位置并绑定数据,绑定什么数据那就看当前中间显示的是星期几了。

分析图如下:但是新的问题又来了,动画执行完毕之后,怎么判断哪些子控件是当前正在显示的呢(中间五个)?由于正在显示的子控件的位置是可以确定的,因为要重写onMeasure(),在onMeasure()方法中可以得到单个子控件的宽度(item_width=getMeasureWidth()/5),动画结束之后,遍历这些子控件,如果x==0的那肯定就是当前正在展示的第一个子控件,x==item_width则是第二个….,剩余的4个就不用判断了,直接将两个移动到左边,两个移动到右边,然后重新为这四个替补设置数据。

Android自定义View(CustomCalendar-定制日历控件)

Android自定义View(CustomCalendar-定制日历控件)

Android自定义View(CustomCalendar-定制日历控件)如图,上部分是自定义日历的效果图,下面是系统自带CalendarView的效果,这两个控件的相关功能需求元素图上都有标注。

系统自带的日历控件能够左右滑动切换月份,效果还是挺酷的(这是我在自定义控件完毕之后才发现的),结果就后悔了,这么酷干嘛还要自定义啊?自定义当然不是为了装逼呐,请认真看需求,我们需要在日期下面显示任务完成情况,当日被切换之后需要标注为灰色圆圈背景,这些都是自带日历控件不可达到的,当然,我们也可以继承系统CalendarView然后试着修改;那为什么不选择开源的日历控件呢?如果我们不会自定义控件或者时间很紧,开源的当然是首选,谁叫我闲的慌,开源的控件也会有些问题,有的可能不够完善很多bug,比较完善的可能内容太多,如果要抽取有用的内容还是需要花一定时间,如果整个库工程都弄过来会造成大量的代码冗余。

另外一点很重要,任务情况需要从服务器上获取,当切换日期之后,日历控件下方要显示那天的任务详情(可能需要请求数据),这么多问题如果去修改开源库工程工作量不一定比自定义小。

综上,还是自定义更适合我,整个日历控件500多行代码就搞定(包括注释、接口、各种变量),后面如果项目需求有变动,改动起来也是so easy! 当然,日常开发中,自带控件能搞定的尽量就用系统自带的。

下面我们一起看看这个控件是怎样实现的。

1、分析怎样自定义这个日历控件呢?可能我们第一反应是GridView+组合控件的方式,GridView用来展示下面日期部分,这种方式实现起来相对比较容易,但是核心的内容(获取某月的天数、具体展示在什么位置)还是得自己做,这种方式代码量也不少,另外这样做也会加大系统性能开销,GridView中同时显示30来个item,item里面还嵌套子控件,之前我们讲控件填充、测量时讲过尽量减少布局的嵌套,这样会造成过多的遍历,一不小心又装逼了,现在的手机那么牛逼,这么点工作量跟我谈什么性能?第二种就是通过自定义View完全绘制出来,只需要一个类搞定。

Android自定义view实现日历打卡签到

Android自定义view实现日历打卡签到

Android⾃定义view实现⽇历打卡签到本⽂实例为⼤家分享了Android⾃定义view实现⽇历打卡签到的具体代码,供⼤家参考,具体内容如下1.说明⾃⼰写⼀个view实现每天签到的功能,设置背景图⽚2.效果图3.主界⾯package com.example.myapplication30;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import java.util.ArrayList;import java.util.Calendar;import java.util.List;public class MainActivity extends AppCompatActivity {//参考⽹址:https:///MacaoPark/article/details/102069775private TextView mTvDaySum;private TextView mTvMonth;private SignView mCvCalendar;private List<SignEntity> data;private Calendar calendar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);mTvDaySum = findViewById(R.id.punch_tv_day_sum);mTvMonth = findViewById(R.id.punch_tv_month);mCvCalendar = findViewById(R.id.punch_cv_calendar);}@Overrideprotected void onStart() {super.onStart();onReady();}@SuppressLint("SetTextI18n")private void onReady() {calendar = Calendar.getInstance();int year = calendar.get(Calendar.YEAR);int month = calendar.get(Calendar.MONTH);//int date = calendar.get(Calendar.DATE);int dayOfMonthToday = calendar.get(Calendar.DAY_OF_MONTH);List<SignDate> signDates = new ArrayList<>();signDates.add(new SignDate(2021, 5, 1, true));signDates.add(new SignDate(2021, 5, 2, true));signDates.add(new SignDate(2021, 5, 3, true));signDates.add(new SignDate(2021, 5, 4, true));signDates.add(new SignDate(2021, 5, 5, true));mTvDaySum.setText("本期连续登录\t"+signDates.size()+"\t天");mTvMonth.setText(year+"年"+getResources().getStringArray(R.array.month_array)[month]+"\t"+dayOfMonthToday+"⽇"); data = new ArrayList<>();for (int i = 1; i <= dayOfMonthToday; i++) {SignEntity signEntity = new SignEntity();if (i == dayOfMonthToday) {signEntity.setDayType(2);} else {signEntity.setDayType(1);}for (int j = 0; j < signDates.size(); j++) {if (signDates.get(j).getDay() == i) {signEntity.setDayType(0);break;} else if (dayOfMonthToday == i) {signEntity.setDayType(2);} else {signEntity.setDayType(1);}}data.add(signEntity);}SignAdapter signAdapter = new SignAdapter(data);mCvCalendar.setAdapter(signAdapter);}}4.适配器package com.example.myapplication30;import java.util.List;/*** SignAdapter* Created by E.M on 2016/4/21.*/public class SignAdapter extends CalendarAdapter {private List<SignEntity> data;public SignAdapter(List<SignEntity> data) {this.data = data;}@Overridepublic SignView.DayType getType(int dayOfMonth) {return SignView.DayType.valueOf(data.get(dayOfMonth - 1).getDayType());}}5.⾃定义viewpackage com.example.myapplication30;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Color;import poseShader;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.RadialGradient;import android.graphics.Rect;import android.graphics.Shader;import android.graphics.SweepGradient;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import java.util.Calendar;/*** 签到⽇历控件* Created by E.M on 2016/4/20.*/public class SignView extends View {private static final String[] WEEK_MARK = {"⼀", "⼆", "三", "四", "五", "六", "⽇"}; private static final int MAX_COLUMN = 7;/*** 周内*/private static final int COLOR_MARKER_WEEKDAY = 0xFF999999;private static final int COLOR_MARKER_WEEKEND = 0xFF1B89CD;/*** 已签到背景⾊*///private static final int COLOR_BACKGROUND_HIGHLIGHT = 0xFFFF0000;/*** 未签到背景⾊*/private static final int COLOR_BACKGROUND_NORMAL = 0xFF9C9C9C;/*** 等待签到背景⾊*/private static final int COLOR_BACKGROUND_WAIT = 0xFFFE7471;/*** 已签到⽂字颜⾊*/private static final int COLOR_TEXT_HIGHLIGHT = 0xFFFFFFFF;/*** 未签到⽂字颜⾊*/private static final int COLOR_TEXT_NORMAL = 0xFF606060;// /**// * 不可⽤⽂字颜⾊// */// private static final int COLOR_TEXT_DISABLED = 0xFFD4D4D4;private static final int MARKER_TEXT_SIZE = 40;private static final int CELL_TEXT_SIZE = 40;private static final int VERTICAL_SPACE = 51;private static final int VERTICAL_MARGIN = 62;private static final int HORIZONTAL_MARGIN = 39;private static final int CELL_SIZE = 80;private static final int WAIT_LINE_SIZE = 14;private int dayOfMonthToday;private int markerTextY;private int verticalCellTop;private int sumDayOfMonth;private int daysOfFirstWeek;private int horizontalSpace;private int deltaTextCellY;private int deltaTextMarkerY;private int verticalSpace;private int verticalMargin;private int horizontalMargin;private int cellSize;private int waitLineSize;private Path waitPath;private Rect waitRect;private Paint paintWeekday;private Paint paintWeekend;private Paint paintTextNormal;private Paint paintTextHighlight;private Paint paintBackgroundWait;private Paint paintBackgroundNormal;private Paint paintBackgroundHighlight;private CalendarAdapter adapter;public SignView(Context context) {this(context, null);}public SignView(Context context, AttributeSet attrs) {this(context, attrs, -1);}public SignView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initResolution();initPaint();initData();}private void initResolution() {// resolutionUtil = ResolutionUtil.getInstance();// verticalSpace = resolutionUtil.formatVertical(VERTICAL_SPACE);// verticalMargin = resolutionUtil.formatVertical(VERTICAL_MARGIN);// horizontalMargin = resolutionUtil.formatHorizontal(HORIZONTAL_MARGIN); // cellSize = resolutionUtil.formatVertical(CELL_SIZE);// waitLineSize = resolutionUtil.formatVertical(WAIT_LINE_SIZE);verticalSpace = VERTICAL_SPACE;verticalMargin = VERTICAL_MARGIN;horizontalMargin = HORIZONTAL_MARGIN;cellSize = CELL_SIZE;waitLineSize = WAIT_LINE_SIZE;}private void initPaint() {// int markerTextSize = resolutionUtil.formatVertical(MARKER_TEXT_SIZE); // int cellTextSize = resolutionUtil.formatVertical(CELL_TEXT_SIZE);int markerTextSize = MARKER_TEXT_SIZE;int cellTextSize = CELL_TEXT_SIZE;paintWeekday = new Paint();paintWeekday.setAntiAlias(true);paintWeekday.setColor(COLOR_MARKER_WEEKDAY);paintWeekday.setTextSize(markerTextSize);paintWeekday.setTextAlign(Paint.Align.CENTER);paintWeekend = new Paint();paintWeekend.setAntiAlias(true);paintWeekend.setColor(COLOR_MARKER_WEEKEND);paintWeekend.setTextSize(markerTextSize);paintWeekend.setTextAlign(Paint.Align.CENTER);paintTextNormal = new Paint();paintTextNormal.setAntiAlias(true);paintTextNormal.setColor(COLOR_TEXT_NORMAL);paintTextNormal.setTextSize(cellTextSize);paintTextNormal.setTextAlign(Paint.Align.CENTER);paintTextHighlight = new Paint();paintTextHighlight.setAntiAlias(true);paintTextHighlight.setColor(COLOR_TEXT_HIGHLIGHT);paintTextHighlight.setTextSize(cellTextSize);paintTextHighlight.setTextAlign(Paint.Align.CENTER);paintBackgroundWait = new Paint();paintBackgroundWait.setAntiAlias(true);paintBackgroundWait.setColor(COLOR_BACKGROUND_WAIT);paintBackgroundWait.setStrokeWidth(2);paintBackgroundWait.setStyle(Paint.Style.STROKE);paintBackgroundNormal = new Paint();paintBackgroundNormal.setAntiAlias(true);paintBackgroundNormal.setColor(COLOR_BACKGROUND_NORMAL);paintBackgroundNormal.setStrokeWidth(2);paintBackgroundNormal.setStyle(Paint.Style.STROKE);paintBackgroundHighlight = new Paint();paintBackgroundHighlight.setAntiAlias(true);paintBackgroundHighlight.setStrokeWidth(2);paintBackgroundHighlight.setStyle(Paint.Style.FILL);//颜⾊//paintBackgroundHighlight.setColor(COLOR_BACKGROUND_HIGHLIGHT);//多种颜⾊数组//int[] colors = {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW,Color.MAGENTA};//float[] position = {0f, 0.2f, 0.4f, 0.6f, 1.0f};//Shader shader1 = new LinearGradient(100,850,600,850,colors,position,Shader.TileMode.CLAMP);//paintBackgroundHighlight.setShader(shader1);//设置背景图⽚/* Bitmap placeholder = BitmapFactory.decodeResource(getResources(), R.mipmap.small);Shader shader1 = new BitmapShader(placeholder, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paintBackgroundHighlight.setShader(shader1);*/}private void initData() {Paint.FontMetricsInt fmiMarker = paintWeekday.getFontMetricsInt();deltaTextMarkerY = -(fmiMarker.bottom - fmiMarker.top) / 2 - fmiMarker.top;markerTextY = verticalMargin + cellSize / 2;Paint.FontMetricsInt fmiCell = paintTextNormal.getFontMetricsInt();deltaTextCellY = -(fmiCell.bottom - fmiCell.top) / 2 - fmiCell.top;verticalCellTop = verticalMargin + cellSize;Calendar calendarToday = Calendar.getInstance();dayOfMonthToday = calendarToday.get(Calendar.DAY_OF_MONTH);int dayOfWeek;sumDayOfMonth = calendarToday.getActualMaximum(Calendar.DAY_OF_MONTH);Calendar calendarFirstDay = Calendar.getInstance();calendarFirstDay.set(Calendar.DAY_OF_MONTH, 1);dayOfWeek = calendarFirstDay.get(Calendar.DAY_OF_WEEK);if (dayOfWeek == Calendar.SUNDAY) {dayOfWeek = 7;} else {dayOfWeek = dayOfWeek - 1;}daysOfFirstWeek = MAX_COLUMN - dayOfWeek + 1;}private void createWaitBackground(int topX, int topY) {waitPath = new Path();waitPath.moveTo(topX, topY + waitLineSize);waitPath.lineTo(topX, topY);waitPath.lineTo(topX + waitLineSize, topY);waitPath.moveTo(topX + cellSize - waitLineSize, topY + cellSize);waitPath.lineTo(topX + cellSize, topY + cellSize);waitPath.lineTo(topX + cellSize, topY + cellSize - waitLineSize);waitRect = new Rect(topX, topY, topX + cellSize, topY + cellSize);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);horizontalSpace = (w - MAX_COLUMN * cellSize - horizontalMargin * 2) / (MAX_COLUMN - 1);}@Overridepublic void draw(Canvas canvas) {super.draw(canvas);drawWeekMark(canvas);drawCellsBackground(canvas);drawCells(canvas);}private void drawWeekMark(Canvas canvas) {int y = markerTextY + deltaTextMarkerY;for (int i = 0; i < 7; i++) {int x = horizontalMargin + i * (horizontalSpace + cellSize)+ cellSize / 2;if (i < 5) {canvas.drawText(WEEK_MARK[i], x, y, paintWeekday);} else {canvas.drawText(WEEK_MARK[i], x, y, paintWeekend);}}}private void drawCellsBackground(Canvas canvas) {for (int i = 1; i <= dayOfMonthToday; i++) {drawCellBackground(canvas, i, getColumnIndex(i), getRowIndex(i));}}/*** 根据⾏列序号绘制⽇期背景** @param canvas 画布* @param dayOfMonth ⽇期* @param column 列序号* @param row ⾏序号*/private void drawCellBackground(Canvas canvas, int dayOfMonth, int column, int row) {int x = horizontalMargin + column * (horizontalSpace + cellSize)+ cellSize / 2;int y = verticalCellTop + verticalSpace * (row + 1) + cellSize * row + cellSize / 2;if (adapter != null) {DayType dayType = adapter.getType(dayOfMonth);switch (dayType) {case WAITING:if (waitPath == null) {createWaitBackground(x - cellSize / 2, y - cellSize / 2);}canvas.drawPath(waitPath, paintBackgroundWait);break;case SIGNED:// canvas.drawCircle(x, y, cellSize/2, paintBackgroundHighlight);// canvas.drawRect(x - 60, y - 60, x + 60, y + 60, paintBackgroundHighlight);// 正⽅形// Bitmap placeholder = BitmapFactory.decodeResource(getResources(), R.mipmap.purtest);// canvas.drawBitmap(placeholder,);wCircle(x, y, cellSize/2, paintBackgroundHighlight);canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.small3),x-40, y-40 , paintBackgroundHighlight); break;default:canvas.drawCircle(x, y, cellSize / 2, paintBackgroundNormal);break;}} else {canvas.drawCircle(x, y, cellSize / 2, paintBackgroundNormal);}}private void drawCells(Canvas canvas) {for (int i = 1; i <= sumDayOfMonth; i++) {drawCell(canvas, i, getColumnIndex(i), getRowIndex(i));}}/*** 根据⾏列序号绘制⽇期** @param canvas 画布* @param dayOfMonth ⽇期* @param column 列序号* @param row ⾏序号*/private void drawCell(Canvas canvas, int dayOfMonth, int column, int row) {int x = horizontalMargin + column * (horizontalSpace + cellSize)+ cellSize / 2;int y = verticalCellTop + verticalSpace * (row + 1) + cellSize * row + cellSize / 2+ deltaTextCellY;if (adapter != null && dayOfMonth <= dayOfMonthToday) {DayType dayType = adapter.getType(dayOfMonth);Paint paint;switch (dayType) {case SIGNED:paint = paintTextHighlight;break;default:paint = paintTextNormal;break;}canvas.drawText(String.valueOf(dayOfMonth), x, y, paint);} else {canvas.drawText(String.valueOf(dayOfMonth), x, y, paintTextNormal);}}/*** 获取列序号** @param dayOfMonth ⽇期* @return 列序号*/private int getColumnIndex(int dayOfMonth) {Calendar calendar = Calendar.getInstance();calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);if (dayOfWeek == Calendar.SUNDAY) {dayOfWeek = 6;} else {dayOfWeek = dayOfWeek - 2;}return dayOfWeek;}/*** 获取⾏序号** @param dayOfMonth ⽇期* @return ⾏序号*/private int getRowIndex(int dayOfMonth) {float weight = (dayOfMonth - daysOfFirstWeek) / (MAX_COLUMN * 1f);double rowIndexDouble = Math.abs(Math.ceil(weight));return (int) rowIndexDouble;}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_UP) {float x = event.getX();float y = event.getY();if (waitPath != null) {if (adapter.getType(dayOfMonthToday).equals(DayType.WAITING)) {if (x >= waitRect.left && y >= waitRect.top && x <= waitRect.right && y <= waitRect.bottom) { if (onTodayClickListener != null) {onTodayClickListener.onTodayClick();}}}}}return true;}public void setAdapter(CalendarAdapter adapter) {this.adapter = adapter;this.invalidate();}public int getDayOfMonthToday() {return dayOfMonthToday;}public void notifyDataSetChanged() {invalidate();}private OnTodayClickListener onTodayClickListener;public void setOnTodayClickListener(OnTodayClickListener onTodayClickListener) {this.onTodayClickListener = onTodayClickListener;}public interface OnTodayClickListener {void onTodayClick();}public enum DayType {/*** 已签到状态,时间已过*/SIGNED(0),/*** 未签到状态,时间已过*/UNSIGNED(1),/*** 等待状态,即当⽇还未签到*/WAITING(2),/*** 不可达到状态,未到时间*/UNREACHABLE(3),/*** 不可⽤状态,⾮当前⽉份*/DISABLED(4);private int value;DayType(int value) {this.value = value;}public int getValue() {return value;}public static DayType valueOf(int value) {switch (value) {case 0:return SIGNED;case 1:return UNSIGNED;case 2:return WAITING;case 3:return UNREACHABLE;case 4:return DISABLED;default:return DISABLED;}}}}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

Android日期选择器实现年月日三级联动

Android日期选择器实现年月日三级联动

Android⽇期选择器实现年⽉⽇三级联动最近项⽬⾥⾯⽤到了⼀个⽇期选择器,实现现在主流的WheelView滑动选择,整理了下,做了个Demo.废话不多说,直接上代码.主布局:activity_main.xml<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="er.mydate.MainActivity"><TextViewandroid:id="@+id/selectDate"android:layout_width="match_parent"android:layout_height="30dp"android:gravity="center"android:onClick="selectDate"android:clickable="true"android:text="⽇期选择" /></RelativeLayout>MainActivity:package er.mydate;import android.app.Activity;import android.os.Bundle;import android.view.Gravity;import android.view.View;import android.view.Window;import android.widget.TextView;import android.widget.Toast;import er.mydate.view.ChangeDatePopwindow;public class MainActivity extends Activity {private TextView selectDate;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(yout.activity_main);selectDate= (TextView) findViewById(R.id.selectDate);}public void selectDate(View v){if (v.getId()==R.id.selectDate){selectDate();}}private String[] selectDate() {final String[] str = new String[10];ChangeDatePopwindow mChangeBirthDialog = new ChangeDatePopwindow(this);mChangeBirthDialog.setDate("2016", "1", "1");mChangeBirthDialog.showAtLocation(selectDate, Gravity.BOTTOM, 0, 0);mChangeBirthDialog.setBirthdayListener(new ChangeDatePopwindow.OnBirthListener() {@Overridepublic void onClick(String year, String month, String day) {// TODO Auto-generated method stubsb.append(year.substring(0, year.length() - 1)).append("-").append(month.substring(0, day.length() - 1)).append("-").append(day); str[0] = year + "-" + month + "-" + day;str[1] = sb.toString();selectDate.setText(year + "-" + month + "-" + day);}});return str;}}主要的类:package er.mydate.view;import android.content.Context;import android.graphics.drawable.ColorDrawable;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.PopupWindow;import android.widget.TextView;import er.mydate.R;import er.mydate.view.wheelview.OnWheelChangedListener;import er.mydate.view.wheelview.OnWheelScrollListener;import er.mydate.view.wheelview.WheelView;import er.mydate.view.wheelview.adapter.AbstractWheelTextAdapter1;import java.util.ArrayList;import java.util.Calendar;/*** Author: Chen.yuan* Email: hubeiqiyuan2010@* Date: 2016/7/28 17:37* Description:⽇期选择window*/public class ChangeDatePopwindow extends PopupWindow implements View.OnClickListener {private Context context;private WheelView wvYear;private WheelView wvMonth;private WheelView wvDay;private TextView btnSure;private TextView btnCancel;private ArrayList<String> arry_years = new ArrayList<String>();private ArrayList<String> arry_months = new ArrayList<String>();private ArrayList<String> arry_days = new ArrayList<String>();private CalendarTextAdapter mYearAdapter;private CalendarTextAdapter mMonthAdapter;private CalendarTextAdapter mDaydapter;private String month;private String day;private String currentYear = getYear();private String currentMonth = getMonth();private String currentDay = getDay();private int maxTextSize = 24;private int minTextSize = 14;private boolean issetdata = false;private String selectYear;private String selectMonth;private String selectDay;private OnBirthListener onBirthListener;this.context = context;View view=View.inflate(context, yout.dialog_myinfo_changebirth,null);wvYear = (WheelView) view.findViewById(R.id.wv_birth_year);wvMonth = (WheelView) view.findViewById(R.id.wv_birth_month);wvDay = (WheelView) view.findViewById(R.id.wv_birth_day);btnSure = (TextView) view.findViewById(R.id.btn_myinfo_sure);btnCancel = (TextView) view.findViewById(R.id.btn_myinfo_cancel);//设置SelectPicPopupWindow的Viewthis.setContentView(view);//设置SelectPicPopupWindow弹出窗体的宽this.setWidth(youtParams.MATCH_PARENT);//设置SelectPicPopupWindow弹出窗体的⾼this.setHeight(youtParams.MATCH_PARENT);//设置SelectPicPopupWindow弹出窗体可点击this.setFocusable(true);//设置SelectPicPopupWindow弹出窗体动画效果// this.setAnimationStyle(R.style.AnimBottom);//实例化⼀个ColorDrawable颜⾊为半透明ColorDrawable dw = new ColorDrawable(0xb0000000);//设置SelectPicPopupWindow弹出窗体的背景this.setBackgroundDrawable(dw);btnSure.setOnClickListener(this);btnCancel.setOnClickListener(this);if (!issetdata) {initData();}initYears();mYearAdapter = new CalendarTextAdapter(context, arry_years, setYear(currentYear), maxTextSize, minTextSize);wvYear.setVisibleItems(5);wvYear.setViewAdapter(mYearAdapter);wvYear.setCurrentItem(setYear(currentYear));initMonths(Integer.parseInt(month));mMonthAdapter = new CalendarTextAdapter(context, arry_months, setMonth(currentMonth), maxTextSize, minTextSize); wvMonth.setVisibleItems(5);wvMonth.setViewAdapter(mMonthAdapter);wvMonth.setCurrentItem(setMonth(currentMonth));initDays(Integer.parseInt(day));mDaydapter = new CalendarTextAdapter(context, arry_days, Integer.parseInt(currentDay) - 1, maxTextSize, minTextSize); wvDay.setVisibleItems(5);wvDay.setViewAdapter(mDaydapter);wvDay.setCurrentItem(Integer.parseInt(currentDay) - 1);wvYear.addChangingListener(new OnWheelChangedListener() {@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {// TODO Auto-generated method stubString currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem());selectYear = currentText;setTextviewSize(currentText, mYearAdapter);currentYear = currentText.substring(0, currentText.length()-1).toString();Log.d("currentYear==",currentYear);setYear(currentYear);initMonths(Integer.parseInt(month));mMonthAdapter = new CalendarTextAdapter(context, arry_months, 0, maxTextSize, minTextSize);wvMonth.setVisibleItems(5);wvMonth.setViewAdapter(mMonthAdapter);wvMonth.setCurrentItem(0);calDays(currentYear, month);}});wvYear.addScrollingListener(new OnWheelScrollListener() {@Overridepublic void onScrollingStarted(WheelView wheel) {// TODO Auto-generated method stub}@Overridepublic void onScrollingFinished(WheelView wheel) {// TODO Auto-generated method stubString currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem());setTextviewSize(currentText, mYearAdapter);}});wvMonth.addChangingListener(new OnWheelChangedListener() {@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {// TODO Auto-generated method stubString currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem());selectMonth = currentText;setTextviewSize(currentText, mMonthAdapter);setMonth(currentText.substring(0, 1));initDays(Integer.parseInt(day));mDaydapter = new CalendarTextAdapter(context, arry_days, 0, maxTextSize, minTextSize); wvDay.setVisibleItems(5);wvDay.setViewAdapter(mDaydapter);wvDay.setCurrentItem(0);calDays(currentYear, month);}});wvMonth.addScrollingListener(new OnWheelScrollListener() {@Overridepublic void onScrollingStarted(WheelView wheel) {// TODO Auto-generated method stub}@Overridepublic void onScrollingFinished(WheelView wheel) {// TODO Auto-generated method stubString currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem());setTextviewSize(currentText, mMonthAdapter);}});wvDay.addChangingListener(new OnWheelChangedListener() {@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {// TODO Auto-generated method stubString currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem());setTextviewSize(currentText, mDaydapter);selectDay = currentText;}});wvDay.addScrollingListener(new OnWheelScrollListener() {@Overridepublic void onScrollingStarted(WheelView wheel) {// TODO Auto-generated method stub}@Overridepublic void onScrollingFinished(WheelView wheel) {// TODO Auto-generated method stubString currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem());setTextviewSize(currentText, mDaydapter);}});}public void initYears() {for (int i = Integer.parseInt(getYear()); i > 1950; i--) {arry_years.add(i + "年");}public void initMonths(int months) {arry_months.clear();for (int i = 1; i <= months; i++) {arry_months.add(i + "⽉");}}public void initDays(int days) {arry_days.clear();for (int i = 1; i <= days; i++) {arry_days.add(i + "⽇");}}private class CalendarTextAdapter extends AbstractWheelTextAdapter1 {ArrayList<String> list;protected CalendarTextAdapter(Context context, ArrayList<String> list, int currentItem, int maxsize, int minsize) { super(context, yout.item_birth_year, NO_RESOURCE, currentItem, maxsize, minsize);this.list = list;setItemTextResource(R.id.tempValue);}@Overridepublic View getItem(int index, View cachedView, ViewGroup parent) {View view = super.getItem(index, cachedView, parent);return view;}@Overridepublic int getItemsCount() {return list.size();}@Overrideprotected CharSequence getItemText(int index) {return list.get(index) + "";}}public void setBirthdayListener(OnBirthListener onBirthListener) {this.onBirthListener = onBirthListener;}@Overridepublic void onClick(View v) {if (v == btnSure) {if (onBirthListener != null) {onBirthListener.onClick(selectYear, selectMonth, selectDay);Log.d("cy",""+selectYear+""+selectMonth+""+selectDay);}} else if (v == btnSure) {} else {dismiss();}dismiss();}public interface OnBirthListener {public void onClick(String year, String month, String day);}/*** 设置字体⼤⼩** @param curriteItemText* @param adapter*/public void setTextviewSize(String curriteItemText, CalendarTextAdapter adapter) {ArrayList<View> arrayList = adapter.getTestViews();String currentText;for (int i = 0; i < size; i++) {TextView textvew = (TextView) arrayList.get(i);currentText = textvew.getText().toString();if (curriteItemText.equals(currentText)) {textvew.setTextSize(maxTextSize);} else {textvew.setTextSize(minTextSize);}}}public String getYear() {Calendar c = Calendar.getInstance();return c.get(Calendar.YEAR)+"";}public String getMonth() {Calendar c = Calendar.getInstance();return c.get(Calendar.MONTH) + 1+"";}public String getDay() {Calendar c = Calendar.getInstance();return c.get(Calendar.DATE)+"";}public void initData() {setDate(getYear(), getMonth(), getDay());this.currentDay = 1+"";this.currentMonth = 1+"";}/*** 设置年⽉⽇** @param year* @param month* @param day*/public void setDate(String year, String month, String day) { selectYear = year + "年";selectMonth = month + "⽉";selectDay = day + "⽇";issetdata = true;this.currentYear = year;this.currentMonth = month;this.currentDay = day;if (year == getYear()) {this.month = getMonth();} else {this.month = 12+"";}calDays(year, month);}/*** 设置年份** @param year*/public int setYear(String year) {int yearIndex = 0;if (!year.equals(getYear())) {this.month = 12+"";} else {this.month = getMonth();}for (int i = Integer.parseInt(getYear()); i > 1950; i--) {if (i == Integer.parseInt(year)) {return yearIndex;}yearIndex++;}return yearIndex;/*** 设置⽉份** @param month* @param month* @return*/public int setMonth(String month) {int monthIndex = 0;calDays(currentYear, month);for (int i = 1; i < Integer.parseInt(this.month); i++) {if (Integer.parseInt(month) == i) {return monthIndex;} else {monthIndex++;}}return monthIndex;}/*** 计算每⽉多少天** @param month* @param year*/public void calDays(String year, String month) {boolean leayyear = false;if (Integer.parseInt(year) % 4 == 0 && Integer.parseInt(year) % 100 != 0) { leayyear = true;} else {leayyear = false;}for (int i = 1; i <= 12; i++) {switch (Integer.parseInt(month)) {case 1:case 3:case 5:case 7:case 8:case 10:case 12:this.day = 31+"";break;case 2:if (leayyear) {this.day = 29+"";} else {this.day = 28+"";}break;case 4:case 6:case 9:case 11:this.day = 30+"";break;}}if (year.equals( getYear()) && month .equals( getMonth())) {this.day = getDay();}}}底部弹出框布局:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android" android:id="@+id/ly_myinfo_changeaddress"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/color_transparent"<LinearLayoutandroid:id="@+id/ly_myinfo_changeaddress_child"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:background="@color/white"android:orientation="vertical" ><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="44dp"><TextViewandroid:id="@+id/btn_myinfo_cancel"android:layout_width="wrap_content"android:layout_height="match_parent"android:paddingLeft="12dp"android:text="取消"android:gravity="center"android:layout_alignParentLeft="true"android:layout_marginRight="15dip"android:textColor="@color/color_e84515"android:textSize="13sp" /><TextViewandroid:id="@+id/btn_myinfo_sure"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_alignParentRight="true"android:gravity="center"android:text="完成"android:textColor="@color/color_e84515"android:paddingRight="12dp"android:textSize="12sp" /></RelativeLayout><TextView xmlns:android="/apk/res/android" android:layout_width="match_parent"android:layout_height="0.5dp"android:background="@color/color_d8d8d8"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="160dip"android:orientation="horizontal"android:gravity="center_vertical"><er.mydate.view.wheelview.WheelViewandroid:id="@+id/wv_birth_year"android:layout_width="0dip"android:layout_weight="1"android:layout_height="match_parent"android:layout_gravity="center_vertical"/><er.mydate.view.wheelview.WheelViewandroid:id="@+id/wv_birth_month"android:layout_width="0dip"android:layout_weight="1"android:layout_height="match_parent"android:layout_gravity="center_vertical"/><er.mydate.view.wheelview.WheelViewandroid:id="@+id/wv_birth_day"android:layout_width="0dip"android:layout_weight="1"android:layout_height="match_parent"android:layout_gravity="center_vertical"/></LinearLayout></LinearLayout></LinearLayout>运⾏效果图:以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

Android基于wheelView的自定义日期选择器

Android基于wheelView的自定义日期选择器

Android基于wheelView的自定义日期选择器系统自带的DatePicker、TimePicker大家都知道,只有这种效果:百度了很多,试了NumberPicker等都不行,本来打算自己写。

网友推荐了一个开源组件WheelView,下下来试了试,发现他已经定义的很完善了,在他的基础上拓展很容易。

现将基于wheelView自定义日期选择器记录如下:一.首先要了解WheelView为我们提供了什么:除了我写的”DateObject”与”StringWheelAdapter”,其余都是WheelView提供的,1. WheelView.java :可滚动的组件,主要方法:setAdapter(new StringWheelAdapter(dateList, 7)); //设置AdaptersetVisibleItems(3); //设置显示几行数据setCyclic(true); //设置是否循环显示数据addChangingListener(onDaysChangedListener) //设置滑动监听器2. WheelAdapter.java : 滑动组件的适配器的接口,子类适配器用于装载数据public interface WheelAdapter {/*** Gets items count* @return the count of wheel items*/public int getItemsCount();/*** Gets a wheel item by index.** @param index the item index* @return the wheel item text or null*/public String getItem(int index);/*** Gets maximum item length. It is used to determine the wheel width.* If -1 is returned there will be used the default wheel width.** @return the maximum item length or -1*/public int getMaximumLength();}3. OnWheelChangedListener.java : 滑动监听器接口public interface OnWheelChangedListener {/*** Callback method to be invoked when current item changed* @param wheel the wheel view whose state has changed* @param oldValue the old value of current item* @param newValue the new value of current item*/void onChanged(WheelView wheel, int oldValue, int newValue);}4.OnWheelScrollListener.java :滚动监听器接口(暂时没用到)5.NumericWheelAdapter.java : 当滚动内容为纯数字时调用的适配器6.DateObject.java : 日期实体类,用于存储、获取选择的数据package kankan.wheel.widget;import java.util.Calendar;public class DateObject extends Object{private int year ;private int month;private int day;private int week;private int hour;private int minute;private String listItem;/*** 日期对象的4个参数构造器,用于设置日期* @param year* @param month* @param day* @author sxzhang*/public DateObject(int year2, int month2, int day2,int week2) {super();this.year = year2;int maxDayOfMonth = Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);if(day2 > maxDayOfMonth){this.month = month2 + 1;this.day = day2 % maxDayOfMonth;}else{this.month = month2;this.day = day2;}this.week = week2 % 7 == 0 ? 7 : week2 % 7;if(day == Calendar.getInstance().get(Calendar.DAY_OF_MONTH)){this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day) +"日"+ " 今天";}else{this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day) +"日"+ getDayOfWeekCN(week);}}/*** 日期对象的2个参数构造器,用于设置时间* @param hour2* @param minute2* @param isHourType true:传入的是hour; false: 传入的是minute* @author sxzhang*/public DateObject(int hour2,int minute2,boolean isHourType) {super();if(isHourType == true && hour2 != -1){ //设置小时if(hour2 > 24){this.hour = hour2 % 24;}elsethis.hour = hour2;this.listItem = this.hour + "时";}else if(isHourType == false && minute2 != -1){ //设置分钟if(minute2 > 60)this.minute = minute2 % 60;elsethis.minute = minute2;this.listItem = this.minute + "分";}}public int getHour() {return hour;}public void setHour(int hour) {this.hour = hour;}public int getMinute() {return minute;}public void setMinute(int minute) { this.minute = minute;}public int getWeek() {return week;}public void setWeek(int week) { this.week = week;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getMonth() {return month;}public void setMonth(int month) { this.month = month;}public int getDay() {return day;}public void setDay(int day) {this.day = day;}public String getListItem() {return listItem;}public void setListItem(String listItem) {this.listItem = listItem;}/*** 根据day_of_week得到汉字星期* @return*/public static String getDayOfWeekCN(int day_of_week){String result = null;switch(day_of_week){case 1:result = "星期日";break;case 2:result = "星期一";break;case 3:result = "星期二";break;case 4:result = "星期三";break;case 5:result = "星期四";break;case 6:result = "星期五";break;case 7:result = "星期六";break;default:break;}return result;}}7.StringWheelAdapter.java :一会儿将定义的滚动内容为字符串的适配器,当内容为字符串时我们就可以随意拓展滑动部分的内容package kankan.wheel.widget;import java.util.ArrayList;/*** The simple String Array wheel adapter**/public class StringWheelAdapter implements WheelAdapter {/** The default items length */public static final int DEFAULT_LENGTH = -1;// itemsprivate ArrayList<DateObject> list;// lengthprivate int length;/*** Constructor* @param items the items* @param length the max items length*/public StringWheelAdapter(ArrayList<DateObject> list, int length) { this.list = list;this.length = length;}@Overridepublic String getItem(int index) {if (index >= 0 && index < list.size()) {return list.get(index).getListItem();}return null;}@Overridepublic int getItemsCount() {return list.size();}@Overridepublic int getMaximumLength() {return length;}}二.了解以后就可以使用他定义我们需要的了。

Android 日历方式显示的日期选择组件

Android 日历方式显示的日期选择组件

Android 日历方式显示的日期选择组件此Widget组件只包含五个类文件:• DateWidget• DateWidgetDayCell• DateWidgetDayHeader• DayStyle• SymbolButton*红色为启动的activityDateWidget.java:Java代码1. package com.iaiai;2.3. import java.text.SimpleDateFormat;4. import java.util.ArrayList;5. import java.util.Calendar;6.7. import android.app.Activity;8. import android.os.Bundle;9. import android.view.Gravity;10. import android.view.V iew;11. import android.widget.Button;12. import android.widget.LinearLayout;13. import youtParams;14. import android.widget.TextView;15.37. public class DateWidget extends Activity {38. private ArrayList<DateWidgetDayCell> days = new ArrayList<DateWidgetDayCell>();39. // private SimpleDateFormat dateMonth = new SimpleDateFormat("MMMM yyyy");40. private Calendar calStartDate = Calendar.getInstance();41. private Calendar calToday = Calendar.getInstance();42. private Calendar calCalendar = Calendar.getInstance();43. private Calendar calSelected = Calendar.getInstance();44. LinearLayout layContent = null;45. Button btnPrev = null;46. Button btnToday = null;47. Button btnNext = null;48. private int iFirstDayOfWeek = Calendar.MONDAY;49. private int iMonthViewCurrentMonth = 0;50. private int iMonthViewCurrentY ear = 0;51. public static final int SELECT_DA TE_REQUEST = 111;52. private static final int iDayCellSize = 38;53. private static final int iDayHeaderHeight = 24;54. private static final int iTotalWidth = (iDayCellSize * 7);55. private TextView tv;56. private int mY ear;57. private int mMonth;58. private int mDay;59.60. @Override61. public void onCreate(Bundle icicle) {62. super.onCreate(icicle);63. iFirstDayOfWeek = Calendar.MONDA Y;64. mY ear = calSelected.get(Calendar.YEAR);65. mMonth = calSelected.get(Calendar.MONTH);66. mDay = calSelected.get(Calendar.DAY_OF_MONTH);67. setContentView(generateContentView());68. calStartDate = getCalendarStartDate();69. DateWidgetDayCell daySelected = updateCalendar();70. updateControlsState();71. if (daySelected != null)72. daySelected.requestFocus();73. }74.75. @Override76. public void onStart() {77. super.onStart();78.79. }80.81. private LinearLayout createLayout(int iOrientation) {82. LinearLayout lay = new LinearLayout(this);83. lay.setLayoutParams(new LayoutParams(84. youtParams.FILL_PARENT,85. youtParams.WRAP_CONTENT));86. lay.setOrientation(iOrientation);87. return lay;88. }89.90. private Button createButton(String sText, int iWidth, int iHeight) {91. Button btn = new Button(this);92. btn.setText(sText);93. btn.setLayoutParams(new LayoutParams(iWidth, iHeight));94. return btn;95. }96.97. private void generateTopButtons(LinearLayout layTopControls) {98. final int iHorPadding = 24;99. final int iSmallButtonWidth = 60;100. btnToday = createButton("", iTotalWidth - iSmallButtonWidth101. - iSmallButtonWidth,102. youtParams.WRAP_CONTENT);103. btnToday.setPadding(iHorPadding, btnToday.getPaddingTop(), iHorPadding, 104. btnToday.getPaddingBottom());105. btnToday.setBackgroundResource(android.R.drawable.btn_default_small); 106.107. SymbolButton btnPrev = new SymbolButton(this,108. SymbolButton.symbol.arrowLeft);109. btnPrev.setLayoutParams(new LayoutParams(iSmallButtonWidth,110. android.view.V youtParams.WRAP_CONTENT));111. btnPrev.setBackgroundResource(android.R.drawable.btn_default_small); 112.113. SymbolButton btnNext = new SymbolButton(this,114. SymbolButton.symbol.arrowRight);115. btnNext.setLayoutParams(new LayoutParams(iSmallButtonWidth,116. android.view.V youtParams.WRAP_CONTENT));117. btnNext.setBackgroundResource(android.R.drawable.btn_default_small); 118.119. // set events120. btnPrev.setOnClickListener(new Button.OnClickListener() {121. public void onClick(View arg0) {122. setPrevV iewItem();123. }124. });125. btnToday.setOnClickListener(new Button.OnClickListener() {126. public void onClick(View arg0) {127.128. setTodayV iewItem();129. String s = calToday.get(Calendar.YEAR) + "/"130. + (calToday.get(Calendar.MONTH) + 1);131. btnToday.setText(s);132. }133. });134. btnNext.setOnClickListener(new Button.OnClickListener() {135. public void onClick(View arg0) {136. setNextV iewItem();137. }138. });139.140. layTopControls.setGravity(Gravity.CENTER_HORIZONTAL);141. layTopControls.addV iew(btnPrev);142. layTopControls.addV iew(btnToday);143. layTopControls.addV iew(btnNext);144. }145.146. private View generateContentView() {147. LinearLayout layMain = createLayout(LinearLayout.VERTICAL);148. layMain.setPadding(8, 8, 8, 8);149. LinearLayout layTopControls = createLayout(LinearLayout.HORIZONTAL); 150.151. layContent = createLayout(LinearLayout.VERTICAL);152. layContent.setPadding(20, 0, 20, 0);153. generateTopButtons(layTopControls);154. generateCalendar(layContent);155. layMain.addView(layTopControls);156. layMain.addView(layContent);157.158. tv = new TextView(this);159. layMain.addView(tv);160. return layMain;161. }162.163. private View generateCalendarRow() {164. LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL); 165. for (int iDay = 0; iDay < 7; iDay++) {166. DateWidgetDayCell dayCell = new DateWidgetDayCell(this,167. iDayCellSize, iDayCellSize);168. dayCell.setItemClick(mOnDayCellClick);169. days.add(dayCell);170. layRow.addV iew(dayCell);171. }172. return layRow;173. }174.175. private View generateCalendarHeader() {176. LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL); 177. for (int iDay = 0; iDay < 7; iDay++) {178. DateWidgetDayHeader day = new DateWidgetDayHeader(this,179. iDayCellSize, iDayHeaderHeight);180. final int iWeekDay = DayStyle.getWeekDay(iDay, iFirstDayOfWeek); 181. day.setData(iWeekDay);182. layRow.addV iew(day);183. }184. return layRow;185. }186.187. private void generateCalendar(LinearLayout layContent) {188. layContent.addView(generateCalendarHeader());189. days.clear();190. for (int iRow = 0; iRow < 6; iRow++) {191. layContent.addView(generateCalendarRow());192. }193. }194.195. private Calendar getCalendarStartDate() {196. calToday.setTimeInMillis(System.currentTimeMillis());197. calToday.setFirstDayOfWeek(iFirstDayOfWeek);198.199. if (calSelected.getTimeInMillis() == 0) {200. calStartDate.setTimeInMillis(System.currentTimeMillis());201. calStartDate.setFirstDayOfWeek(iFirstDayOfWeek);202. } else {203. calStartDate.setTimeInMillis(calSelected.getTimeInMillis());204. calStartDate.setFirstDayOfWeek(iFirstDayOfWeek);205. }206.207. UpdateStartDateForMonth();208.209. return calStartDate;210. }211.212. private DateWidgetDayCell updateCalendar() {213. DateWidgetDayCell daySelected = null;214. boolean bSelected = false;215. final boolean bIsSelection = (calSelected.getTimeInMillis() != 0); 216. final int iSelectedY ear = calSelected.get(Calendar.YEAR);217. final int iSelectedMonth = calSelected.get(Calendar.MONTH);218. final int iSelectedDay = calSelected.get(Calendar.DAY_OF_MONTH); 219. calCalendar.setTimeInMillis(calStartDate.getTimeInMillis());220. for (int i = 0; i < days.size(); i++) {221. final int iY ear = calCalendar.get(Calendar.YEAR);222. final int iMonth = calCalendar.get(Calendar.MONTH);223. final int iDay = calCalendar.get(Calendar.DAY_OF_MONTH); 224. final int iDayOfWeek = calCalendar.get(Calendar.DAY_OF_WEEK); 225. DateWidgetDayCell dayCell = days.get(i);226. // check today227. boolean bToday = false;228. if (calToday.get(Calendar.YEAR) == iY ear)229. if (calToday.get(Calendar.MONTH) == iMonth)230. if (calToday.get(Calendar.DAY_OF_MONTH) == iDay)231. bToday = true;232. // check holiday233. boolean bHoliday = false;234. if ((iDayOfWeek == Calendar.SA TURDAY)235. || (iDayOfWeek == Calendar.SUNDAY))236. bHoliday = true;237. if ((iMonth == Calendar.JANUARY) && (iDay == 1))238. bHoliday = true;239.240. dayCell.setData(iY ear, iMonth, iDay, bToday, bHoliday,241. iMonthViewCurrentMonth);242. bSelected = false;243. if (bIsSelection)244. if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth)245. && (iSelectedY ear == iY ear)) {246. bSelected = true;247. }248. dayCell.setSelected(bSelected);249. if (bSelected)250. daySelected = dayCell;251. calCalendar.add(Calendar.DAY_OF_MONTH, 1);252. }253. layContent.invalidate();254. return daySelected;255. }256.257. private void UpdateStartDateForMonth() {258. iMonthViewCurrentMonth = calStartDate.get(Calendar.MONTH);259. iMonthViewCurrentY ear = calStartDate.get(Calendar.YEAR);260. calStartDate.set(Calendar.DAY_OF_MONTH, 1);261. UpdateCurrentMonthDisplay();262. // update days for week263. int iDay = 0;264. int iStartDay = iFirstDayOfWeek;265. if (iStartDay == Calendar.MONDAY) {266. iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY; 267. if (iDay < 0)268. iDay = 6;269. }270. if (iStartDay == Calendar.SUNDAY) {271. iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; 272. if (iDay < 0)273. iDay = 6;274. }275. calStartDate.add(Calendar.DAY_OF_WEEK, -iDay);276. }277.278. private void UpdateCurrentMonthDisplay() {279. String s = calCalendar.get(Calendar.YEAR) + "/"280. + (calCalendar.get(Calendar.MONTH) + 1);// dateMonth.format(calCalendar.getTime());281. btnToday.setText(s);282. mY ear = calCalendar.get(Calendar.YEAR);283. }284.285. private void setPrevViewItem() {286. iMonthViewCurrentMonth--;287. if (iMonthViewCurrentMonth == -1) {288. iMonthViewCurrentMonth = 11;289. iMonthViewCurrentY ear--;290. }291. calStartDate.set(Calendar.DAY_OF_MONTH, 1);292. calStartDate.set(Calendar.MONTH, iMonthViewCurrentMonth);293. calStartDate.set(Calendar.YEAR, iMonthViewCurrentY ear);294. UpdateStartDateForMonth();295. updateCalendar();296.297. }298.299. private void setTodayViewItem() {300. calToday.setTimeInMillis(System.currentTimeMillis());301. calToday.setFirstDayOfWeek(iFirstDayOfWeek);302. calStartDate.setTimeInMillis(calToday.getTimeInMillis());303. calStartDate.setFirstDayOfWeek(iFirstDayOfWeek);304. UpdateStartDateForMonth();305. updateCalendar();306. }307.308. private void setNextViewItem() {309. iMonthViewCurrentMonth++;310. if (iMonthViewCurrentMonth == 12) {311. iMonthV iewCurrentMonth = 0;312. iMonthViewCurrentY ear++;313. }314. calStartDate.set(Calendar.DAY_OF_MONTH, 1);315. calStartDate.set(Calendar.MONTH, iMonthViewCurrentMonth);316. calStartDate.set(Calendar.YEAR, iMonthViewCurrentY ear);317. UpdateStartDateForMonth();318. updateCalendar();319.320. }321.322. private DateWidgetDayCell.OnItemClick mOnDayCellClick = new DateWidgetDayCell.OnItemClick() {323. public void OnClick(DateWidgetDayCell item) {324. calSelected.setTimeInMillis(item.getDate().getTimeInMillis());325. item.setSelected(true);326. updateCalendar();327. updateControlsState();328. }329. };330.331. private void updateControlsState() {332. SimpleDateFormat dateFull = new SimpleDateFormat("d MMMM yyyy");333. mY ear = calSelected.get(Calendar.YEAR);334. mMonth = calSelected.get(Calendar.MONTH);335. mDay = calSelected.get(Calendar.DAY_OF_MONTH);336. tv.setText(new StringBuilder().append(mY ear).append("/")337. .append(format(mMonth + 1)).append("/").append(format(mDay))338. .append("-----").append(dateFull.format(calSelected.getTime())));339. }340.341. private String format(int x) {342. String s = "" + x;343. if (s.length() == 1)344. s = "0" + s;345. return s;346. }347.348. }DateWidgetDayCell.java:Java代码1. package com.iaiai;2.3. import java.util.Calendar;4.5. import android.content.Context;6. import android.graphics.Canvas;7. import android.graphics.LinearGradient;8. import android.graphics.Paint;9. import android.graphics.Rect;10. import android.graphics.RectF;11. import android.graphics.Shader;12. import android.view.KeyEvent;13. import android.view.MotionEvent;14. import android.view.V iew;15. import android.view.animation.AlphaAnimation;16. import youtParams;17.39. public class DateWidgetDayCell extends View {40. // types41. public interface OnItemClick {42. public void OnClick(DateWidgetDayCell item);43. }44.45. public static int ANIM_ALPHA_DURA TION = 100;46. // fields47. private final static float fTextSize = 22;48. private final static int iMargin = 1;49. private final static int iAlphaInactiveMonth = 0x88;50.51. // fields52. private int iDateY ear = 0;53. private int iDateMonth = 0;54. private int iDateDay = 0;55.56. // fields57. private OnItemClick itemClick = null;58. private Paint pt = new Paint();59. private RectF rect = new RectF();60. private String sDate = "";61.62. // fields63. private boolean bSelected = false;64. private boolean bIsActiveMonth = false;65. private boolean bToday = false;66. private boolean bHoliday = false;67. private boolean bTouchedDown = false;68.69. // methods70. public DateWidgetDayCell(Context context, int iWidth, int iHeight) {71. super(context);72. setFocusable(true);73. setLayoutParams(new LayoutParams(iWidth, iHeight));74. }75.76. public boolean getSelected() {77. return this.bSelected;78. }79.80. @Override81. public void setSelected(boolean bEnable) {82. if (this.bSelected != bEnable) {83. this.bSelected = bEnable;84. this.invalidate();85. }86. }87.88. public void setData(int iY ear, int iMonth, int iDay, boolean bToday,89. boolean bHoliday, int iActiveMonth) {90. iDateY ear = iY ear;91. iDateMonth = iMonth;92. iDateDay = iDay;93.94. this.sDate = Integer.toString(iDateDay);95. this.bIsActiveMonth = (iDateMonth == iActiveMonth);96. this.bToday = bToday;97. this.bHoliday = bHoliday;98. }99.100. public void setItemClick(OnItemClick itemClick) {101. this.itemClick = itemClick;102. }103.104. private int getTextHeight() {105. return (int) (-pt.ascent() + pt.descent());106. }107.108. @Override109. public boolean onKeyDown(int keyCode, KeyEvent event) { 110. boolean bResult = super.onKeyDown(keyCode, event);111. if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) 112. || (keyCode == KeyEvent.KEYCODE_ENTER)) {113. doItemClick();114. }115. return bResult;116. }117.118. @Override119. public boolean onKeyUp(int keyCode, KeyEvent event) {120. boolean bResult = super.onKeyUp(keyCode, event);121. return bResult;122. }123.124. public void doItemClick() {125. if (itemClick != null)126. itemClick.OnClick(this);127. }128.129. @Override130. protected void onFocusChanged(boolean gainFocus, int direction, 131. Rect previouslyFocusedRect) {132. super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 133. invalidate();134. }135.136. public Calendar getDate() {137. Calendar calDate = Calendar.getInstance();138. calDate.clear();139. calDate.set(Calendar.YEAR, iDateYear);140. calDate.set(Calendar.MONTH, iDateMonth);141. calDate.set(Calendar.DAY_OF_MONTH, iDateDay);142. return calDate;143. }144.145. @Override146. protected void onDraw(Canvas canvas) {147. super.onDraw(canvas);148.149. // init rectangles150. rect.set(0, 0, this.getWidth(), this.getHeight());151. rect.inset(1, 1);152.153. // drawing154. final boolean bFocused = IsV iewFocused();155.156. drawDayV iew(canvas, bFocused);157. drawDayNumber(canvas, bFocused);158. }159.160. private void drawDayView(Canvas canvas, boolean bFocused) {161. if (bSelected || bFocused) {162. LinearGradient lGradBkg = null;163.164. if (bFocused) {165. lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,166. DayStyle.iColorBkgFocusDark,167. DayStyle.iColorBkgFocusLight, Shader.TileMode.CLAMP); 168. }169.170. if (bSelected) {171. lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,172. DayStyle.iColorBkgSelectedDark,173. DayStyle.iColorBkgSelectedLight, Shader.TileMode.CLAMP); 174. }175.176. if (lGradBkg != null) {177. pt.setShader(lGradBkg);178. canvas.drawRect(rect, pt);179. }180.181. pt.setShader(null);182.183. } else {184.185. pt.setColor(DayStyle.getColorBkg(bHoliday, bToday));186. if (!bIsActiveMonth)187. pt.setAlpha(iAlphaInactiveMonth);188. canvas.drawRect(rect, pt);189. }190. }191.192. public void drawDayNumber(Canvas canvas, boolean bFocused) {193. // draw day number194. pt.setTypeface(null);195. pt.setAntiAlias(true);196. pt.setShader(null);197. pt.setFakeBoldText(true);198. pt.setTextSize(fTextSize);199.200. pt.setUnderlineText(false);201. if (bToday)202. pt.setUnderlineText(true);203.204. int iTextPosX = (int) rect.right - (int) pt.measureText(sDate);205. int iTextPosY = (int) rect.bottom + (int) (-pt.ascent())206. - getTextHeight();207.208. iTextPosX -= ((int) rect.width() >> 1)209. - ((int) pt.measureText(sDate) >> 1);210. iTextPosY -= ((int) rect.height() >> 1) - (getTextHeight() >> 1); 211.212. // draw text213. if (bSelected || bFocused) {214. if (bSelected)215. pt.setColor(DayStyle.iColorTextSelected);216. if (bFocused)217. pt.setColor(DayStyle.iColorTextFocused);218. } else {219. pt.setColor(DayStyle.getColorText(bHoliday, bToday)); 220. }221.222. if (!bIsActiveMonth)223. pt.setAlpha(iAlphaInactiveMonth);224.225. canvas.drawText(sDate, iTextPosX, iTextPosY + iMargin, pt); 226.227. pt.setUnderlineText(false);228. }229.230. public boolean IsV iewFocused() {231. return (this.isFocused() || bTouchedDown);232. }233.234. @Override235. public boolean onTouchEvent(MotionEvent event) {236. boolean bHandled = false;237. if (event.getAction() == MotionEvent.ACTION_DOWN) { 238. bHandled = true;239. bTouchedDown = true;240. invalidate();241. startAlphaAnimIn(DateWidgetDayCell.this);242. }243. if (event.getAction() == MotionEvent.ACTION_CANCEL) { 244. bHandled = true;245. bTouchedDown = false;246. invalidate();247. }248. if (event.getAction() == MotionEvent.ACTION_UP) {249. bHandled = true;250. bTouchedDown = false;251. invalidate();252. doItemClick();253. }254. return bHandled;255. }256.257. public static void startAlphaAnimIn(View view) {258. AlphaAnimation anim = new AlphaAnimation(0.5F, 1);259. anim.setDuration(ANIM_ALPHA_DURA TION);260. anim.startNow();261. view.startAnimation(anim);262. }263.264. }DateWidgetDayHeader.java:Java代码1. package com.iaiai;2.3. import java.util.Calendar;4.5. import android.content.Context;6. import android.graphics.Canvas;7. import android.graphics.Paint;8. import android.graphics.RectF;9. import android.view.V iew;10. import youtParams;11.33. public class DateWidgetDayHeader extends View {34. // fields35. private final static int iDayHeaderFontSize = 12;36.37. // fields38. private Paint pt = new Paint();39. private RectF rect = new RectF();40. private int iWeekDay = -1;41. private boolean bHoliday = false;42.43. // methods44. public DateWidgetDayHeader(Context context, int iWidth, int iHeight) {45. super(context);46. setLayoutParams(new LayoutParams(iWidth, iHeight));47. }49. public void setData(int iWeekDay) {50. this.iWeekDay = iWeekDay;51. this.bHoliday = false;52. if ((iWeekDay == Calendar.SA TURDAY) || (iWeekDay == Calendar.SUNDAY))53. this.bHoliday = true;54. }55.56. private void drawDayHeader(Canvas canvas) {57. if (iWeekDay != -1) {58. // background59. pt.setColor(DayStyle.getColorFrameHeader(bHoliday));60. canvas.drawRect(rect, pt);61.62. // text63. pt.setTypeface(null);64. pt.setTextSize(iDayHeaderFontSize);65. pt.setAntiAlias(true);66. pt.setFakeBoldText(true);67. pt.setColor(DayStyle.getColorTextHeader(bHoliday));68.69. final int iTextPosY = getTextHeight();70. final String sDayName = DayStyle.getWeekDayName(iWeekDay);71.72. // draw day name73. final int iDayNamePosX = (int) rect.left74. + ((int) rect.width() >> 1)75. - ((int) pt.measureText(sDayName) >> 1);76. canvas.drawText(sDayName, iDayNamePosX, rect.top + iTextPosY + 2,77. pt);78. }79. }80.81. private int getTextHeight() {82. return (int) (-pt.ascent() + pt.descent());83. }84.85. @Override86. protected void onDraw(Canvas canvas) {87. super.onDraw(canvas);88.89. // init rectangles90. rect.set(0, 0, this.getWidth(), this.getHeight());91. rect.inset(1, 1);93. // drawing94. drawDayHeader(canvas);95. }96.97. }DayStyle.java:Java代码26. public class DayStyle {27. // methods28.29. private static String[] getWeekDayNames() {30. String[] vec = new String[10];31. // vec[Calendar.SUNDAY] = "Sun";32. // vec[Calendar.MONDAY] = "Mon";33. // vec[Calendar.TUESDAY] = "Tue";34. // vec[Calendar.WEDNESDAY] = "Wed";35. // vec[Calendar.THURSDAY] = "Thu";36. // vec[Calendar.FRIDAY] = "Fri";37. // vec[Calendar.SA TURDAY] = "Sat";38.39. vec[Calendar.SUNDAY] = "日";40. vec[Calendar.MONDAY] = "月";41. vec[Calendar.TUESDAY] = "火";42. vec[Calendar.WEDNESDAY] = "水";43. vec[Calendar.THURSDAY] = "木";44. vec[Calendar.FRIDAY] = "金";45. vec[Calendar.SA TURDAY] = "土";46. return vec;47. }48.49. public static String getWeekDayName(int iDay) {50. return vecStrWeekDayNames[iDay];51. }52.53. // fields54. private final static String[] vecStrWeekDayNames = getWeekDayNames();55.56. // fields57. public final static int iColorFrameHeader = 0xff666666;58. public final static int iColorFrameHeaderHoliday = 0xff707070;59. public final static int iColorTextHeader = 0xffcccccc;60. public final static int iColorTextHeaderHoliday = 0xffd0d0d0;62. public final static int iColorText = 0xffdddddd;63. public final static int iColorBkg = 0xff888888;64. public final static int iColorTextHoliday = 0xfff0f0f0;65. public final static int iColorBkgHoliday = 0xffaaaaaa;66.67. public final static int iColorTextToday = 0xff002200;68. public final static int iColorBkgToday = 0xff88bb88;69.70. public final static int iColorTextSelected = 0xff001122;71. public final static int iColorBkgSelectedLight = 0xffbbddff;72. public final static int iColorBkgSelectedDark = 0xff225599;73.74. public final static int iColorTextFocused = 0xff221100;75. public final static int iColorBkgFocusLight = 0xffffddbb;76. public final static int iColorBkgFocusDark = 0xffaa5500;77.78. // methods79. public static int getColorFrameHeader(boolean bHoliday) {80. if (bHoliday)81. return iColorFrameHeaderHoliday;82. return iColorFrameHeader;83. }84.85. public static int getColorTextHeader(boolean bHoliday) {86. if (bHoliday)87. return iColorTextHeaderHoliday;88. return iColorTextHeader;89. }90.91. public static int getColorText(boolean bHoliday, boolean bToday) {92. if (bToday)93. return iColorTextToday;94. if (bHoliday)95. return iColorTextHoliday;96. return iColorText;97. }98.99. public static int getColorBkg(boolean bHoliday, boolean bToday) { 100. if (bToday)101. return iColorBkgToday;102. if (bHoliday)103. return iColorBkgHoliday;104. return iColorBkg;105. }106.107. public static int getWeekDay(int index, int iFirstDayOfWeek) { 108. int iWeekDay = -1;109.110. if (iFirstDayOfWeek == Calendar.MONDAY) {111. iWeekDay = index + Calendar.MONDAY;112. if (iWeekDay > Calendar.SA TURDAY)113. iWeekDay = Calendar.SUNDAY;114. }115.116. if (iFirstDayOfWeek == Calendar.SUNDAY) {117. iWeekDay = index + Calendar.SUNDAY;118. }119.120. return iWeekDay;121. }122.123. }SymbolButton.java:Java代码1. package com.iaiai;2.3. import android.content.Context;4. import android.graphics.Canvas;5. import android.graphics.Paint;6. import android.graphics.RectF;7. import android.widget.Button;8.30. public class SymbolButton extends Button {31. // fields32. private static final int iColor = 0xffaaaaaa;33. private static final int iColorActive = 0xff442200;34.35. // fields36. public enum symbol {37. none, arrowLeft, arrowRight38. };39.40. // fields41. private Paint pt = new Paint();42. private RectF rect = new RectF();43. private RectF rectDraw = new RectF();44. private symbol symbolType = symbol.none;45.46. // methods47. public SymbolButton(Context context, symbol symbolType) {48. super(context);49. this.symbolType = symbolType;50. }51.52. @Override53. public void onDraw(Canvas canvas) {54. super.onDraw(canvas);55.56. pt.setAntiAlias(true);57. pt.setStrokeCap(Paint.Cap.ROUND);58.59. rectDraw.set(0, 0, getWidth(), getHeight());60. rectDraw.left += 6;61. rectDraw.right -= 6;62. rectDraw.top += 4;63. rectDraw.bottom -= 8;64.65. if (symbolType != symbol.none) {66. pt.setStrokeWidth(5);67.68. pt.setColor(iColor);69. if (this.isPressed() || this.isFocused())70. pt.setColor(iColorActive);71.72. drawArrow(canvas);73. }74. }75.76. private void drawArrow(Canvas canvas) {77. rect.set(rectDraw);78. rect.inset(15, 5);79. canvas.drawLine(rect.left, rect.centerY(), rect.right, rect.centerY(),80. pt);81. if (symbolType == symbol.arrowRight) {82. canvas.drawLine(rect.right, rect.centerY(), rect.right - 6,83. rect.top, pt);84. canvas.drawLine(rect.right, rect.centerY(), rect.right - 6,85. rect.bottom, pt);86. }87. if (symbolType == symbol.arrowLeft) {88. canvas.drawLine(rect.left, rect.centerY(), rect.left + 6, rect.top,89. pt);90. canvas.drawLine(rect.left, rect.centerY(), rect.left + 6,91. rect.bottom, pt);92. }93. }94.95. }。

Android自定义wheelview实现滚动日期选择器

Android自定义wheelview实现滚动日期选择器

Android⾃定义wheelview实现滚动⽇期选择器本⽂实例为⼤家分享了Android实现滚动⽇期选择器的具体代码,供⼤家参考,具体内容如下wheelview滚动效果的View这段时间需要⽤到⼀个时间选择器,但是不能使⽤⽇期对话框,因为它是筛选条件框架下的,只能是View!这个WheelView改造后可以达到要求!这个wheelview框架使⽤的类不多,就⼏个,还有⼀些资源⽂件。

我根据这个框架设计了⽇期的选择器。

主页⾯:第⼀种⽇期选择器页⾯:动态效果:使⽤:具体的实现是⼀个LoopView的类,这是⼀个继承View的类!理解LoopView的公开⽅法就可以了。

1.布局⽂件<LinearLayout xmlns:android="/apk/res/android" xmlns:app="/apk/res-auto"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#fff"><com.example.wheelview.loopview.LoopViewandroid:layout_marginTop="50dp"android:id="@+id/loopView"android:layout_width="match_parent"android:layout_height="150dp"app:awv_textsize="18"/></LinearLayout>2.控制代码package com.example.wheelview.activity;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Toast;import com.example.wheelview.R;import com.example.wheelview.loopview.LoopView;import com.example.wheelview.loopview.OnItemSelectedListener;import java.util.ArrayList;public class MyActivity extends Activity {private Toast toast;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);final LoopView loopView = (LoopView) findViewById(R.id.loopView);ArrayList<String> list = new ArrayList<String>();for (int i = 0; i < 15; i++) {list.add("item " + i);}//设置是否循环播放// loopView.setNotLoop();//滚动监听loopView.setListener(new OnItemSelectedListener() {@Overridepublic void onItemSelected(int index) {if (toast == null) {toast = Toast.makeText(MyActivity.this, "item " + index, Toast.LENGTH_SHORT);}toast.setText("item " + index);toast.show();}});//设置原始数据loopView.setItems(list);}}那个⽇期选择器就是使⽤三个LoopView结合⽽成的!LoopView类⾥⾯控制字体颜⾊和横线颜⾊的地⽅://中间选中的字体颜⾊:灰⾊:0xff313131,橙⾊:0xffec6f1acenterTextColor = typedArray.getInteger(R.styleable.androidWheelView_awv_centerTextColor, 0xffec6f1a);//没被选中的字体的颜⾊outerTextColor = typedArray.getInteger(R.styleable.androidWheelView_awv_outerTextColor, 0xffafafaf);//中间字体上下两条横线的颜⾊dividerColor = typedArray.getInteger(R.styleable.androidWheelView_awv_dividerTextColor, 0xffc5c5c5);其他的控制可以参考我的代码我的项⽬的代码:我的代码中有⼀个时间的⼯具类,可以很⽅便的取到任何时间,你也可以在⽇期选择器中多加⼀个按钮,设置到今天的⽇期。

Android自定义日期段选择控件功能(开始时间-结束时间)

Android自定义日期段选择控件功能(开始时间-结束时间)

Android⾃定义⽇期段选择控件功能(开始时间-结束时间)开发中碰到个需求,需要在⼀个空间中选择完成开始和结束时间。

实现的过程⾛的是程序员开发的⽼路⼦,找到轮⼦后⾃⼰改吧改吧就成了。

当时做的时候有⼏个需求:1.当天为最⼤的结束⽇期,2.最⼤选择范围1年,3.开始时间和结束时间可以为同⼀天。

如有其他需求实现,可以参考代码改进⼀下。

先上效果图:视频点击后的虚影是屏幕录制的原因。

实现步骤:(如有缺失什么资源,请告知。

开始时间和结束时间显⽰⾃⼰布局内添加就可以)1.⾃定义控件属性<declare-styleable name="MyCalendar"><attr name="dateformat" format="string"></attr><attr name="titleSize" format="dimension"></attr><attr name="titleColor" format="color"></attr><attr name="goIcon" format="reference"></attr><attr name="preIcon" format="reference"></attr><attr name="dayInMonthColor" format="color"></attr><attr name="dayOutMonthcolor" format="color"></attr><attr name="todayColor" format="color"></attr><attr name="todayEmptycircleColor" format="color"></attr><attr name="todayFillcircleColor" format="color"></attr><attr name="calendarbackground" format="color|reference"></attr></declare-styleable>2.⾃定义控件代码/*** @Description: 可以选择时间范围的⽇历控件* @Author MengXY* @Emil mxy_2012_1@* @Date 2019/1/8*/public class CalendarView extends LinearLayout implements View.OnClickListener{private TextView title;private RecyclerView recyclerView;private RelativeLayout layout_calendar_gonext;private RelativeLayout layout_calendar_goup;private LinearLayoutManager linearLayoutManager;private Calendar curDate = Calendar.getInstance();//从服务器获取的⽇期private Date dateFromServer;//外层主recyclerview的adapterprivate MainRvAdapter mainAdapter;private List<CalendarCell> months = new ArrayList<>();private Context context;//相关属性private int titleColor;private int titleSize;private int enableSelectColor;private int disableSeletColor;private int todayColor;private int todayEmptyColor;private int todayFillColor;/** 初始⽇期为当前⽇期前⼀年*/private String time;private long timeBefor;private long timeNow;private List<String> titles = new ArrayList<>();//点击的开始时间与结束时间private Date sDateTime;private Date eDateTime;private boolean isSelectingSTime = true;private HashMap<Integer, SubRvAdapter> allAdapters = new HashMap<>();public CalendarView(Context context) {this(context, null);}public CalendarView(Context context, AttributeSet attrs) {this(context, attrs, 0);}private int maxSelect = 13;public CalendarView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCalendar);titleColor = ta.getColor(R.styleable.MyCalendar_titleColor, Color.WHITE);titleSize = (int) ta.getDimension(R.styleable.MyCalendar_titleSize, 15);enableSelectColor = ta.getColor(R.styleable.MyCalendar_dayInMonthColor, context.getResources().getColor(R.color.text_lable));disableSeletColor = ta.getColor(R.styleable.MyCalendar_dayOutMonthcolor, context.getResources().getColor(R.color.text_unenable)); todayColor = ta.getColor(R.styleable.MyCalendar_todayColor, Color.BLUE);todayEmptyColor = ta.getColor(R.styleable.MyCalendar_todayEmptycircleColor, Color.CYAN);todayFillColor = ta.getColor(R.styleable.MyCalendar_todayFillcircleColor, Color.CYAN);ta.recycle();this.context = context;init(context);}//该⽅法⽤于设置从服务器获取的时间,如果没有从服务器获取的时间将使⽤⼿机本地时间private void initTime() {Calendar calendar = Calendar.getInstance(); //得到⽇历calendar.setTime(new Date());calendar.add(Calendar.MONTH,-(maxSelect-1));time = DateUtils.formatData(calendar.getTime(),Constant.TFORMATE_YMD);timeBefor = DateUtils.getDataTime(time);String now = DateUtils.formatData(new Date(),Constant.TFORMATE_YMD);timeNow = DateUtils.getDataTime(now);// LogUtils.e("之前⽇期:"+time+"=="+timeBefor);// LogUtils.e("当前⽇期:"+now+"=="+timeNow);curDate = DateUtil.strToCalendar(time, Constant.TFORMATE_YMD);dateFromServer = DateUtil.strToDate(time, Constant.TFORMATE_YMD);}private void init(Context context) {bindView(context);renderCalendar();}private void bindView(Context context) {View view = LayoutInflater.from(context).inflate(yout.appoint_calendarview, this, false);title = (TextView) view.findViewById(R.id.calendar_title);title.setTextColor(titleColor);title.setTextSize(titleSize);layout_calendar_gonext = view.findViewById(yout_calendar_gonext);layout_calendar_goup = view.findViewById(yout_calendar_goup);layout_calendar_gonext.setOnClickListener(this);layout_calendar_goup.setOnClickListener(this);recyclerView = (RecyclerView) view.findViewById(R.id.calendar_rv);linearLayoutManager = new LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false);recyclerView.setLayoutManager(linearLayoutManager);PagerSnapHelper snapHelper = new PagerSnapHelper();snapHelper.attachToRecyclerView(recyclerView);addView(view);}public void renderCalendar() {months.clear();initTime();for (int i = 0; i < maxSelect; i++) {ArrayList<Date> cells = new ArrayList<>();if (i != 0) {curDate.add(Calendar.MONTH, 1);//后推⼀个⽉} else {curDate.add(Calendar.MONTH, 0);//当前⽉}Calendar calendar = (Calendar) curDate.clone();//将⽇历设置到当⽉第⼀天calendar.set(Calendar.DAY_OF_MONTH, 1);//获得当⽉第⼀天是星期⼏,如果是星期⼀则返回1此时1-1=0证明上个⽉没有多余天数int prevDays = calendar.get(Calendar.DAY_OF_WEEK) - 1;//将calendar在1号的基础上向前推prevdays天。

Android自定义View实现左右滑动选择出生年份

Android自定义View实现左右滑动选择出生年份

Android⾃定义View实现左右滑动选择出⽣年份⾃定义view的第三篇,模仿的是微博运动界⾯的个⼈出⽣⽇期设置view,先看看我的效果图:⽀持设置初始年份,左右滑动选择出⽣年份,对应的TextView的值也会改变。

这个动画效果弄了好久,感觉还是⽐较⽣硬,与微博那个还是有点区别。

⼤家有改进的⽅案,欢迎⼀起交流。

⾃定义View四部曲,这⾥依旧是这个套路,看看怎么实现的。

1.⾃定义view的属性:在res/values/ 下建⽴⼀个attrs.xml ,在⾥⾯定义我们的属性以及声明我们的整个样式。

<?xml version="1.0" encoding="utf-8"?><resources>//⾃定义属性名,定义公共属性<attr name="titleSize" format="dimension"></attr><attr name="titleText" format="string"></attr><attr name="titleColor" format="color"></attr><attr name="outCircleColor" format="color"></attr><attr name="inCircleColor" format="color"></attr><attr name="lineColor" format="color"></attr><declare-styleable name="MyScrollView"><attr name="titleSize"></attr><attr name="titleColor"></attr><attr name="lineColor"></attr></declare-styleable></resources>依次定义了字体⼤⼩,字体颜⾊,线的颜⾊3个属性,format是值该属性的取值类型。

android实现双日期选择控件(可隐藏日,只显示年月)

android实现双日期选择控件(可隐藏日,只显示年月)

android实现双⽇期选择控件(可隐藏⽇,只显⽰年⽉)在安卓开发中,会碰到选开始⽇期和结束⽇期的问题。

特别是在使⽤Pad时,如果弹出⼀个Dialog,能够同时选择开始⽇期和结束⽇期,那将是极好的。

我在开发中在DatePickerDialog的基础上做了修改,实现了这种Dialog。

效果如下:具体实现⽅法为:先新建⼀个安卓项⽬DoubleDatePicker,在res/layout⽂件夹下新建date_picker_dialog.xml,内容如下:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_horizontal"android:orientation="horizontal"android:paddingTop="10dp" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_horizontal"android:orientation="vertical"android:padding="5dip" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="开始⽇期" /><DatePickerandroid:id="@+id/datePickerStart"android:layout_width="wrap_content"android:layout_height="wrap_content"android:calendarViewShown="false" /></LinearLayout><ImageViewandroid:layout_width="wrap_content"android:layout_height="fill_parent"android:src="@drawable/fenge" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_horizontal"android:orientation="vertical"android:padding="5dip" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="结束⽇期" /><DatePickerandroid:id="@+id/datePickerEnd"android:layout_width="wrap_content"android:layout_height="wrap_content"android:calendarViewShown="false" /></LinearLayout></LinearLayout>然后,在src的默认包下新建⽂件DoubleDatePickerDialog.java,内容如下:/** Copyright (C) 2007 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at*** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.example.doubledatepicker;import ng.reflect.Field;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.DialogInterface.OnClickListener;import android.os.Bundle;import youtInflater;import android.view.View;import android.widget.DatePicker;import android.widget.DatePicker.OnDateChangedListener;/*** A simple dialog containing an {@link android.widget.DatePicker}.** <p>* See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>* guide.* </p>*/public class DoubleDatePickerDialog extends AlertDialog implements OnClickListener, OnDateChangedListener { private static final String START_YEAR = "start_year";private static final String END_YEAR = "end_year";private static final String START_MONTH = "start_month";private static final String END_MONTH = "end_month";private static final String START_DAY = "start_day";private static final String END_DAY = "end_day";private final DatePicker mDatePicker_start;private final DatePicker mDatePicker_end;private final OnDateSetListener mCallBack;/*** The callback used to indicate the user is done filling in the date.*/public interface OnDateSetListener {/*** @param view* The view associated with this listener.* @param year* The year that was set.* @param monthOfYear* The month that was set (0-11) for compatibility with* {@link java.util.Calendar}.* @param dayOfMonth* The day of the month that was set.*/void onDateSet(DatePicker startDatePicker, int startYear, int startMonthOfYear, int startDayOfMonth,DatePicker endDatePicker, int endYear, int endMonthOfYear, int endDayOfMonth);}/*** @param context* The context the dialog is to run in.* @param callBack* How the parent is notified that the date is set.* @param year* The initial year of the dialog.* @param monthOfYear* The initial month of the dialog.* @param dayOfMonth* The initial day of the dialog.*/public DoubleDatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) { this(context, 0, callBack, year, monthOfYear, dayOfMonth);}public DoubleDatePickerDialog(Context context, int theme, OnDateSetListener callBack, int year, int monthOfYear,int dayOfMonth) {this(context, 0, callBack, year, monthOfYear, dayOfMonth, true);}/*** @param context* The context the dialog is to run in.* @param theme* the theme to apply to this dialog* @param callBack* How the parent is notified that the date is set.* @param year* The initial year of the dialog.* @param monthOfYear* The initial month of the dialog.* @param dayOfMonth* The initial day of the dialog.*/public DoubleDatePickerDialog(Context context, int theme, OnDateSetListener callBack, int year, int monthOfYear,int dayOfMonth, boolean isDayVisible) {super(context, theme);mCallBack = callBack;Context themeContext = getContext();setButton(BUTTON_POSITIVE, "确定", this);setButton(BUTTON_NEGATIVE, "取消", this);// setButton(BUTTON_POSITIVE,// themeContext.getText(android.R.string.date_time_done), this);setIcon(0);LayoutInflater inflater = (LayoutInflater) themeContext.getSystemService(YOUT_INFLATER_SERVICE);View view = inflater.inflate(yout.date_picker_dialog, null);setView(view);mDatePicker_start = (DatePicker) view.findViewById(R.id.datePickerStart);mDatePicker_end = (DatePicker) view.findViewById(R.id.datePickerEnd);mDatePicker_start.init(year, monthOfYear, dayOfMonth, this);mDatePicker_end.init(year, monthOfYear, dayOfMonth, this);// updateTitle(year, monthOfYear, dayOfMonth);// 如果要隐藏当前⽇期,则使⽤下⾯⽅法。

Android日期显示和日期选择库

Android日期显示和日期选择库

Android⽇期显⽰和⽇期选择库⽇期显⽰和选择类库,可以⽤来选择⼀段连续的和多个不连续的⽇期,具体的UI完全抽象出来了,可以⾼度⾃定义()⽀持的功能:1、选择⼀段连续的和多个不连续的⽇期2、提供了两个⼯具类(SingleMonthSelector、CalendarSelector)⽤来处理单个⽉和多个连续⽉⽇期的选择3、可以拦截选择事件,当选择的⽇期长度有限制或某些特殊的⽇期不可以选择时,可以中断这次选择事件4、SingleMonthSelector、CalendarSelector两个⼯具类都⽀持状态保存,可以restore之前的状态5、UI显⽰可以⾮常灵活的进⾏⾃定义,可以为每个⽉中的天指定不同的layout,还可以为每⽉的⾏和列(6⾏7列)指定不同的装饰器6、⼀个礼拜的第⼀天并不完全⼀致,现在⽀持(SUNDAY、SATURDAY、MONDAY)三种7、为了在layout的时候能实时的查看具体的显⽰样式,所以提供了editor mode⽀持,在开发调试的时候还是⽐较⽅便的8、⽀持API+8以上版本如何使⽤在Gradle⽂件中加⼊依赖compile 'com.tubb.calendarselector.library:calendar-selector:0.1.1'使⽤MonthView来显⽰⽉,这个是我们的⾃定义View,主要⼯作是组合显⽰某个⽉的天数<com.tubb.calendarselector.library.MonthViewandroid:id="@+id/ssMv"android:layout_width="match_parent"android:layout_height="300dp"sc:sc_firstday_week="sunday"sc:sc_draw_monthday_only="false"sc:sc_month="2016-3"/>为了⽅便,我们提供两个⼯具类来进⾏⽇期的选择功能,SingleMonthSelector⽤来进⾏单个⽉的选择,CalendarSelector⽤来进⾏多个连续⽉的选择,我们也为这两个⼯具类提供了状态保持的功能,为了在必要的时候进⾏状态的恢复,给⽤户更好⼀点的体验,具体使⽤可以查看StateSavedActivity使⽤SingleMonthSelectorsingleMonthSelector.bind(monthView);使⽤CalendarSelector (这⾥有点要注意的是:还不⽀持ListView,针对这种情况直接使⽤RecyclerView好了)calendarSelector.bind(containerViewGroup, monthView, itemPosition);我们为这两个⽇期选择⼯具类都提供了两种模式来⽀持选择连续(SEGMENT)和不连续(INTERVAL)的⼀段时间SEGMENT MODEselector = new CalendarSelector(data, CalendarSelector.Mode.SEGMENT);selector.setSegmentSelectListener(new SegmentSelectListener() {@Overridepublic void onSegmentSelect(FullDay startDay, FullDay endDay) {Log.d(TAG, "segment select " + startDay.toString() + " : " + endDay.toString());}@Overridepublic boolean onInterceptSelect(FullDay selectingDay) { // one day interceptif(SCDateUtils.isToday(selectingDay.getYear(), selectingDay.getMonth(), selectingDay.getDay())){Toast.makeText(CalendarSelectorActivity.this, "Today can't be selected", Toast.LENGTH_SHORT).show();return true;}return super.onInterceptSelect(selectingDay);}@Overridepublic boolean onInterceptSelect(FullDay startDay, FullDay endDay) { // segment days interceptint differDays = SCDateUtils.countDays(startDay.getYear(), startDay.getMonth(), startDay.getDay(),endDay.getYear(), endDay.getMonth(), endDay.getDay());Log.d(TAG, "differDays " + differDays);if(differDays > 10) {Toast.makeText(CalendarSelectorActivity.this, "Selected days can't more than 10", Toast.LENGTH_SHORT).show();return true;}return super.onInterceptSelect(startDay, endDay);}@Overridepublic void selectedSameDay(FullDay sameDay) { // selected the same daysuper.selectedSameDay(sameDay);}});INTERVAL modeselector = new SingleMonthSelector(CalendarSelector.Mode.INTERVAL);selector.setIntervalSelectListener(new IntervalSelectListener() {@Overridepublic void onIntervalSelect(List<FullDay> selectedDays) {Log.d(TAG, "interval selected days " + selectedDays.toString());}@Overridepublic boolean onInterceptSelect(List<FullDay> selectedDays, FullDay selectingDay) {if(selectedDays.size() >= 5) {Toast.makeText(SingleMonthSelectorActivity.this, "Selected days can't more than 5", Toast.LENGTH_LONG).show();return true;}return super.onInterceptSelect(selectedDays, selectingDay);}});在这两种模式下我们都提供了选择事件的拦截功能,这样就有能⼒来实现⼀些限制,⽐如⽇期长度的限制、某些特殊⽇期不可选择等具体如何使⽤可以查看⽰例程序 SingleMonthSelectorActivity 和 CalendarSelectorActivity如何⾃定义我们为MonthView的显⽰提供了⾮常灵活的⾃定义功能,MonthView本⾝就是⼀个功能完善的⾃定义View,并且具体某天的显⽰都可以在layout⽂件中配置<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:tools="/tools"><TextViewandroid:id="@+id/tvDay"android:layout_width="30dp"android:layout_height="30dp"android:textSize="@dimen/t_16"tools:text="0"android:layout_gravity="center"android:gravity="center"android:textColor="@color/color_dayview_text_selector"android:background="@drawable/drawable_custom_dayview_text_bg"/></FrameLayout>为了⽐较灵活的实现上⾯的⾃定义功能,我们特意抽象出来⼀个接⼝DayViewInflater,只要实现这个接⼝,并进⾏相应的设置(MonthView.setSCMonth(scMonth, new CustomDayViewInflater(context)))就⾏public class CustomDayViewInflater extends DayViewInflater{public CustomDayViewInflater(Context context) {super(context);}@Overridepublic DayViewHolder inflateDayView(ViewGroup container) {View dayView = mLayoutInflater.inflate(yout_dayview_custom, container, false);return new CustomDayViewHolder(dayView);}public static class CustomDayViewHolder extends DayViewHolder{protected TextView tvDay;private int mPrevMonthDayTextColor;private int mNextMonthDayTextColor;public CustomDayViewHolder(View dayView) {super(dayView);tvDay = (TextView) dayView.findViewById(Day);mPrevMonthDayTextColor = ContextCompat.getColor(mContext, com.tubb.calendarselector.library.R.color.c_999999);mNextMonthDayTextColor = ContextCompat.getColor(mContext, com.tubb.calendarselector.library.R.color.c_999999);}@Overridepublic void setCurrentMonthDayText(FullDay day, boolean isSelected) {tvDay.setText(String.valueOf(day.getDay()));tvDay.setSelected(isSelected);}@Overridepublic void setPrevMonthDayText(FullDay day) {tvDay.setTextColor(mPrevMonthDayTextColor);tvDay.setText(String.valueOf(day.getDay()));}@Overridepublic void setNextMonthDayText(FullDay day) {tvDay.setTextColor(mNextMonthDayTextColor);tvDay.setText(String.valueOf(day.getDay()));}}}既然是⽇期的选择,那么会有两种状态(选中、未选中)之间的切换,我们也把这个状态切换的接⼝暴露出来了(DayViewHolder.setCurrentMonthDayText(FullDay day, boolean isSelected)),这样我们就可以在状态切换的时候弄些动画什么的,具体的可以查看AnimDayViewInflater⽰例程序@Overridepublic void setCurrentMonthDayText(FullDay day, boolean isSelected) {boolean oldSelected = tvDay.isSelected();tvDay.setText(String.valueOf(day.getDay()));tvDay.setSelected(isSelected);// view selected animationif(!oldSelected && isSelected){AnimatorSet animatorSet = new AnimatorSet();animatorSet.setInterpolator(AnimationUtils.loadInterpolator(mContext, android.R.anim.bounce_interpolator));animatorSet.play(ObjectAnimator.ofFloat(tvDay, "scaleX", 0.5f, 1.0f)).with(ObjectAnimator.ofFloat(tvDay, "scaleY", 0.5f, 1.0f));animatorSet.setDuration(500).start();}}在有些情况下可能会为MonthView的⾏和列加⼀些装饰显得更美观⼀点,这个功能我们也是⽀持的,具体如何实现可以查看⽰例程序@Overridepublic Decor inflateHorizontalDecor(ViewGroup container, int row, int totalRow) {return new Decor(mLayoutInflater.inflate(yout.view_horizontal_decor, container, false), true);}@Overridepublic Decor inflateVerticalDecor(ViewGroup container, int col, int totalCol) {return new Decor(mLayoutInflater.inflate(yout.view_vertical_decor, container, false), true);}我们还为 MonthView提供了⼀些⾃定的属性,⽐如只显⽰本⽉的⽇期、指定⼀个星期的哪天为第⼀天,还有⼀些为开发调试时候⽅便⽽加⼊的属性等<resources><declare-styleable name="MonthView"><!-- only draw the month day, or not, default is false --><attr name="sc_draw_monthday_only" format="boolean"/><!-- start day of a week, we support (sunday、monday and saturday) --><attr name="sc_firstday_week" format="enum"><enum name="sunday" value="1"/><enum name="monday" value="2"/><enum name="saturday" value="7"/></attr><!-- editor mode only --><!-- test selected days (format:1,2,3,4) --><attr name="sc_selected_days" format="string"/><!-- test month (format:2016-3) --><attr name="sc_month" format="string"/></declare-styleable></resources>以上就是本⽂的全部内容,希望对⼤家学习Android软件编程有所帮助。

安卓 自定义 日期和时间选择器,在一个布局中,可以直接调用

安卓 自定义 日期和时间选择器,在一个布局中,可以直接调用

安卓自定义日期和时间选择器,在一个布局中,可以直接调用先看效果,效果不符合,就不要用看了。

安卓提供自己的日期选择和时间选择,但是样式并不是自己想要的,如果非要把他们放在一起,会发现,样式不好看,而且时间和日期选择控件的大小不好控制,甚至根本没法放在一行上,所以实现自定义日期时间选择器有两种方式1.自己写自定义控件,需要能滚动的WheelView,虽然网上有三方的WheelView,但是我们自己还要懂自己如何计算日期时间,时间确实比较麻烦,我们要去学习日历,很费劲2.就是自己去根据安卓自己的日期和时间控件,进行组合,而这样,我们就需要解决两个问题a.样式问题;自己添加了安卓自己的日期控件会发现,各个版本样式不一样,当在一个系统运行效果是这样,但换个系统,样式就不一样了。

那么就需要自己强制定义一个样式,如上图的样式是android:Theme.Holo.Light.Dialog需要在style.xml自定义样式MyDialogStyleBottom[html] view plain copy<!-- 自定义dialogActivity的样式--><style name="MyDialogStyleBottom" parent="android:Theme.Holo.Light.Dialog"> <item name="android:windowAnimationStyle">@style/AnimBottom</item><item name="android:windowFrame">@null</item><!-- 边框--><item name="android:windowIsFloating">false</item><!-- 是否浮现在activity之上--><item name="android:windowIsTranslucent">true</item><!-- 半透明--><item name="android:windowNoTitle">true</item><!-- 无标题--><item name="android:windowBackground">@android:color/transparent</item><!-- 背景透明--><item name="android:backgroundDimEnabled">true</item><!-- 模糊--></style>那么需要自己的activity样式采用这个,就需要manifest配置如下[html] view plain copy<span style="white-space:pre"> </span><activityandroid:name=".DatePickActivity"android:theme="@style/MyDialogStyleBottom" ></activity>b.就是控件大小问题用的时候,发现当强制将两个控件放在一行,会导致日期或时间显示不全,无论怎么调整布局宽度,都无法显示完全,在查看源码时后看到,安卓自己的时间和日期选择器都会用到numberpicker,就可以从这里着手,它们都是FrameLayout的子类,只需要找到其中的numberpicker,进行重新调整位置就行[java] view plain copy<span style="white-space:pre"> </span>/*** 数据初始化*/private void init() {datePicker.setCalendarViewShown(false);timePicker.setIs24HourView(true);resizePikcer(datePicker);// 调整datepicker大小resizePikcer(timePicker);// 调整timepicker大小String str = getIntent().getStringExtra("date");if (TextUtils.isEmpty(str)) {System.out.println("isempty");datestrold = "";datestr = "";} else {datestr = str;datestrold = str;}}[java] view plain copy<span style="white-space:pre"> </span>/*** 调整FrameLayout大小** @param tp*/private void resizePikcer(FrameLayout tp) {List<NumberPicker> npList = findNumberPicker(tp);for (NumberPicker np : npList) {resizeNumberPicker(np);}}[java] view plain copy<span style="white-space:pre"> </span>/** 调整numberpicker大小*/private void resizeNumberPicker(NumberPicker np) {youtParams params = new youtParams(Util.dip2px(this, 45),LayoutParams.WRAP_CONTENT);params.setMargins(Util.dip2px(this, 5), 0, Util.dip2px(this, 5), 0);np.setLayoutParams(params);}[java] view plain copy<span style="white-space:pre"> </span>/*** 得到viewGroup里面的numberpicker组件** @param viewGroup* @return*/private List<NumberPicker> findNumberPicker(ViewGroup viewGroup) {List<NumberPicker> npList = new ArrayList<NumberPicker>();View child = null;if (null != viewGroup) {for (int i = 0; i < viewGroup.getChildCount(); i++) {child = viewGroup.getChildAt(i);if (child instanceof NumberPicker) {npList.add((NumberPicker) child);} else if (child instanceof LinearLayout) {List<NumberPicker> result = findNumberPicker((ViewGroup) child);if (result.size() > 0) {return result;}}}}return npList;}DatePickActivity.java[java] view plain copy@ContentView(yout.activity_date_pick)public class DatePickActivity extends Activity {@ViewInject(R.id.date_picker)private DatePicker datePicker;@ViewInject(R.id.time_picker)private TimePicker timePicker;private String datestrold;private String datestr;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ViewUtils.inject(this);init();}/*** 数据初始化*/private void init() {datePicker.setCalendarViewShown(false);timePicker.setIs24HourView(true);resizePikcer(datePicker);// 调整datepicker大小resizePikcer(timePicker);// 调整timepicker大小String str = getIntent().getStringExtra("date");if (TextUtils.isEmpty(str)) {System.out.println("isempty");datestrold = "";datestr = "";} else {datestr = str;datestrold = str;}}/*** 实现onTouchEvent触屏函数但点击屏幕时** @param v*/@OnClick(R.id.repair_date_other)public void exit(View v) {back(false);}/*** 调整FrameLayout大小** @param tp*/private void resizePikcer(FrameLayout tp) {List<NumberPicker> npList = findNumberPicker(tp);for (NumberPicker np : npList) {resizeNumberPicker(np);}}/** 调整numberpicker大小*/private void resizeNumberPicker(NumberPicker np) {youtParams params = new youtParams(Util.dip2px(this, 45),LayoutParams.WRAP_CONTENT);params.setMargins(Util.dip2px(this, 5), 0, Util.dip2px(this, 5), 0);np.setLayoutParams(params);}/*** 得到viewGroup里面的numberpicker组件** @param viewGroup* @return*/private List<NumberPicker> findNumberPicker(ViewGroup viewGroup) { List<NumberPicker> npList = new ArrayList<NumberPicker>();View child = ull;if (null != viewGroup) {for (int i = 0; i < viewGroup.getChildCount(); i++) {child = viewGroup.getChildAt(i);if (child instanceof NumberPicker) {npList.add((NumberPicker) child);} else if (child instanceof LinearLayout) {List<NumberPicker> result = findNumberPicker((ViewGroup) child);if (result.size() > 0) {return result;}}}}return npList;}/*** 点击取消** @param v*/@OnClick(R.id.repair_date_sel_cancel)public void cancel(View v) {back(true);}/*** 点击确定** @param v*/@OnClick(R.id.repair_date_sel_ok)public void ok(View v) {back(false);}/*** 处理返回按键*/@Overridepublic void onBackPressed() {back(true);super.onBackPressed();}/*** 关闭调用old为true则不变,false则改变** @param old是否不变*/private void back(boolean old) {// 获取时间选择Intent intent = new Intent();if (old) {intent.putExtra("date", datestrold);} else {datestr = getData();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");try {Date date = sdf.parse(datestr);if (!compare(date))return;intent.putExtra("date", datestr);setResult(Activity.RESULT_OK, intent);} catch (ParseException e) {e.printStackTrace();}}finish();}// 比较时间private boolean compare(Date dt1) {Date curDate = new Date(System.currentTimeMillis());if (dt1.getTime() > curDate.getTime()) {System.out.println("选的时间大于现在的时间");rn true;} else if (dt1.getTime() < curDate.getTime()) {Util.showToast(this, "预约时间必须大于当前时间");return false;} else {// 相等System.out.println("相等");return false;}}private String getData() {StringBuilder str = new StringBuilder().append(datePicker.getYear()).append("-").append((datePicker.getMonth() + 1) < 10 ? "0" + (datePicker.getMonth() + 1): (datePicker.getMonth() + 1)).append("-").append((datePicker.getDayOfMonth() < 10) ? "0" + datePicker.getDayOfMonth(): datePicker.getDayOfMonth()).append(" ").append((timePicker.getCurrentHour() < 10) ? "0" + timePicker.getCurrentHour(): timePicker.getCurrentHour()).append(":").append((timePicker.getCurrentMinute() < 10) ? "0" + timePicker.getCurrentMinute(): timePicker.getCurrentMinute());return str.toString();}}activity_date_pick.xml[html] view plain copy<?xml version="1.0" encoding="utf-8"?>android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:background="@color/transparent"android:gravity="center_horizontal"android:orientation="vertical" ><Viewandroid:id="@+id/repair_date_other"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/><eLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/igray" ><Buttonandroid:id="@+id/repair_date_sel_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:background="@color/transparent"android:text="取消"android:textColor="@color/blue"android:textSize="20sp" /><Buttonandroid:id="@+id/repair_date_sel_ok"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:background="@color/transparent"android:textColor="@color/blue"android:text="确定"android:textSize="20sp" /></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white"android:orientation="horizontal"><DatePickerandroid:id="@+id/date_picker"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="5"></DatePicker><TimePickerandroid:id="@+id/time_picker"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="4"android:visibility="visible"/></LinearLayout></LinearLayout></RelativeLayout>。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Android基于wheelView的自定义日期选择器系统自带的DatePicker、TimePicker大家都知道,只有这种效果:百度了很多,试了NumberPicker等都不行,本来打算自己写。

网友推荐了一个开源组件WheelView,下下来试了试,发现他已经定义的很完善了,在他的基础上拓展很容易。

现将基于wheelView自定义日期选择器记录如下:一.首先要了解WheelView为我们提供了什么:除了我写的”DateObject”与”StringWheelAdapter”,其余都是WheelView提供的,1. WheelView.java :可滚动的组件,主要方法:setAdapter(new StringWheelAdapter(dateList, 7)); //设置AdaptersetVisibleItems(3); //设置显示几行数据setCyclic(true); //设置是否循环显示数据addChangingListener(onDaysChangedListener) //设置滑动监听器2. WheelAdapter.java : 滑动组件的适配器的接口,子类适配器用于装载数据public interface WheelAdapter {/*** Gets items count* @return the count of wheel items*/public int getItemsCount();/*** Gets a wheel item by index.** @param index the item index* @return the wheel item text or null*/public String getItem(int index);/*** Gets maximum item length. It is used to determine the wheel width.* If -1 is returned there will be used the default wheel width.** @return the maximum item length or -1*/public int getMaximumLength();}3. OnWheelChangedListener.java : 滑动监听器接口public interface OnWheelChangedListener {/*** Callback method to be invoked when current item changed* @param wheel the wheel view whose state has changed* @param oldValue the old value of current item* @param newValue the new value of current item*/void onChanged(WheelView wheel, int oldValue, int newValue);}4.OnWheelScrollListener.java :滚动监听器接口(暂时没用到)5.NumericWheelAdapter.java : 当滚动内容为纯数字时调用的适配器6.DateObject.java : 日期实体类,用于存储、获取选择的数据package kankan.wheel.widget;import java.util.Calendar;public class DateObject extends Object{private int year ;private int month;private int day;private int week;private int hour;private int minute;private String listItem;/*** 日期对象的4个参数构造器,用于设置日期* @param year* @param month* @param day* @author sxzhang*/public DateObject(int year2, int month2, int day2,int week2) {super();this.year = year2;int maxDayOfMonth = Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);if(day2 > maxDayOfMonth){this.month = month2 + 1;this.day = day2 % maxDayOfMonth;}else{this.month = month2;this.day = day2;}this.week = week2 % 7 == 0 ? 7 : week2 % 7;if(day == Calendar.getInstance().get(Calendar.DAY_OF_MONTH)){this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day) +"日"+ " 今天";}else{this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day) +"日"+ getDayOfWeekCN(week);}}/*** 日期对象的2个参数构造器,用于设置时间* @param hour2* @param minute2* @param isHourType true:传入的是hour; false: 传入的是minute* @author sxzhang*/public DateObject(int hour2,int minute2,boolean isHourType) {super();if(isHourType == true && hour2 != -1){ //设置小时if(hour2 > 24){this.hour = hour2 % 24;}elsethis.hour = hour2;this.listItem = this.hour + "时";}else if(isHourType == false && minute2 != -1){ //设置分钟if(minute2 > 60)this.minute = minute2 % 60;elsethis.minute = minute2;this.listItem = this.minute + "分";}}public int getHour() {return hour;}public void setHour(int hour) {this.hour = hour;}public int getMinute() {return minute;}public void setMinute(int minute) { this.minute = minute;}public int getWeek() {return week;}public void setWeek(int week) { this.week = week;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getMonth() {return month;}public void setMonth(int month) { this.month = month;}public int getDay() {return day;}public void setDay(int day) {this.day = day;}public String getListItem() {return listItem;}public void setListItem(String listItem) {this.listItem = listItem;}/*** 根据day_of_week得到汉字星期* @return*/public static String getDayOfWeekCN(int day_of_week){String result = null;switch(day_of_week){case 1:result = "星期日";break;case 2:result = "星期一";break;case 3:result = "星期二";break;case 4:result = "星期三";break;case 5:result = "星期四";break;case 6:result = "星期五";break;case 7:result = "星期六";break;default:break;}return result;}}7.StringWheelAdapter.java :一会儿将定义的滚动内容为字符串的适配器,当内容为字符串时我们就可以随意拓展滑动部分的内容package kankan.wheel.widget;import java.util.ArrayList;/*** The simple String Array wheel adapter**/public class StringWheelAdapter implements WheelAdapter {/** The default items length */public static final int DEFAULT_LENGTH = -1;// itemsprivate ArrayList<DateObject> list;// lengthprivate int length;/*** Constructor* @param items the items* @param length the max items length*/public StringWheelAdapter(ArrayList<DateObject> list, int length) { this.list = list;this.length = length;}@Overridepublic String getItem(int index) {if (index >= 0 && index < list.size()) {return list.get(index).getListItem();}return null;}@Overridepublic int getItemsCount() {return list.size();}@Overridepublic int getMaximumLength() {return length;}}二.了解以后就可以使用他定义我们需要的了。

相关文档
最新文档