博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android自定义日历控件(继承系统控件实现)
阅读量:4969 次
发布时间:2019-06-12

本文共 7428 字,大约阅读时间需要 24 分钟。

Android自定义日历控件(继承系统控件实现)

51509146.jpg

主要步骤

  1. 编写布局
  2. 继承LinearLayout设置子控件
  3. 设置数据
  4. 继承TextView实现有圆圈背景的TextView
  5. 添加Attribute
  6. 添加长按事件

1.编写布局

2.继承LinearLayout设置子控件

public class CalendarView extends LinearLayout {    private ImageView btnPre;    private ImageView btnNext;    private TextView txtData;    private GridView gridView;    private Calendar calendar = Calendar.getInstance();    private String displayFormat;    public NewViewListener viewListener;    public void setViewListener(NewViewListener viewListener) {        this.viewListener = viewListener;    }    public CalendarView(Context context) {        super(context);    }    public CalendarView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        initControl(context, attrs);    }    public CalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initControl(context, attrs);    }    private void initControl(Context context, AttributeSet attributeSet) {        bindControl(context);        bindControlEvent();        setAttribute(attributeSet);        renderCalender();    }    private void bindControl(Context context) {        LayoutInflater.from(context).inflate(R.layout.new_view, this);        btnNext = (ImageView) findViewById(R.id.btn_next);        btnPre = (ImageView) findViewById(R.id.btn_pre);        txtData = (TextView) findViewById(R.id.txtData);        gridView = (GridView) findViewById(R.id.grid);    }    private void bindControlEvent() {        btnNext.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                calendar.add(Calendar.MONTH, +1);                renderCalender();            }        });        btnPre.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                calendar.add(Calendar.MONTH, -1);                renderCalender();            }        });    } }

3.设置数据

private void renderCalender() {        //返回"月+日"格式的数据        SimpleDateFormat sdf = new SimpleDateFormat(displayFormat, Locale.CHINA);        txtData.setText(sdf.format(calendar.getTime()));        ArrayList
cells = new ArrayList<>(); Calendar calendar2 = (Calendar) this.calendar.clone(); //设置月的第一天为1 calendar2.set(Calendar.DAY_OF_MONTH, 1); //获取当前周数的前一天 int prevDays = calendar2.get(Calendar.DAY_OF_WEEK) - 1; //运算日历加上加前一周 calendar2.add(Calendar.DAY_OF_MONTH, -prevDays); int maxCellCount = 6 * 7; //将日历里的日期数据添加到ArrayList while (cells.size() < maxCellCount) { cells.add(calendar2.getTime()); calendar2.add(Calendar.DAY_OF_MONTH, 1); } gridView.setAdapter(new MyAdapter(getContext(), cells)); gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView
parent, View view, int position, long id) { if (viewListener == null) { return false; } else { viewListener.onItemLongPress((Date) parent.getItemAtPosition(position)); return true; } } }); } private class MyAdapter extends ArrayAdapter
{ LayoutInflater layoutInflater; MyAdapter(@NonNull Context context, ArrayList
dates) { super(context, R.layout.calendar_text_day, dates); layoutInflater = LayoutInflater.from(context); } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { Date date = getItem(position); if (convertView == null) { convertView = layoutInflater.inflate(R.layout.calendar_text_day, parent, false); } int day = date.getDate(); ((CalendarTextView) convertView).setText(String.valueOf(day)); Date now = new Date(); boolean isSameMonth = false; if (date.getMonth() == now.getMonth()) { isSameMonth = true; } if (isSameMonth) { ((CalendarTextView) convertView).setTextColor(Color.DKGRAY); } if (now.getDate() == date.getDate() && now.getMonth() == date.getMonth() && now.getYear() == date.getYear()) { ((CalendarTextView) convertView).setNow(true); } return convertView; } }

4. 圆圈背景TextView

public class CalendarTextView extends AppCompatTextView {    private Paint paint;    private boolean isNow = false;    public void setNow(boolean now) {        isNow = now;    }    public CalendarTextView(Context context) {        super(context);    }    public CalendarTextView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        initControl();    }    public CalendarTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initControl();    }    private void initControl() {        paint = new Paint();        paint.setStyle(Paint.Style.STROKE);        paint.setColor(Color.RED);        paint.setStrokeWidth(2);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (isNow) {            canvas.translate(getWidth() / 2, getHeight() / 2);            canvas.drawCircle(0, 0, getWidth() / 2, paint);            setTextColor(Color.RED);        }    }}

5.添加Attribute

  1. 添加attrs文件

  2. 将Arrtibute参数设置到控件

    private void setAttribute(AttributeSet attributeSet) { TypedArray ta = getContext().obtainStyledAttributes(attributeSet, R.styleable.CalendarView); try { displayFormat = ta.getString(R.styleable.CalendarView_dateFormat); if (displayFormat == null) { displayFormat = "MMM yyy"; } } finally { ta.recycle(); } }

  3. 在布局中加入命名控件引入

    <com.example.jiyang.newview.CalendarView xmlns:CalendarView="http://schemas.android.com/apk/res/com.example.jiyang.newview" android:id="@+id/newView" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" CalendarView:dateFormat="MMMM yyyy" />

6.添加长按事件

  1. 定义长按接口

    public interface NewViewListener { void onItemLongPress(Date day); }

  2. CalenderView中调用
    gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (viewListener == null) { return false; } else { viewListener.onItemLongPress((Date) parent.getItemAtPosition(position)); return true; } } });
  3. Activity中实现接口方法

    @Override public void onItemLongPress(Date day) { DateFormat df = SimpleDateFormat.getDateInstance(); Toast.makeText(this, df.format(day), Toast.LENGTH_SHORT).show(); }

总结

  • Attribute的使用

    1. 定义attrs文件
    2. 注意命名空间。自定义View不能使用app:,而要使用xmlns:自定义一个命名空间
    3. TypedArray放入try{}finaly{}中,要在finally中释放TypedArray typedArray.recycle()
  • 通过继承布局实现自定义View时,加载布局

    需要LayoutInflater.from(context).inflate(R.layout.new_view, this);不能LayoutInflater.from(context).inflate(R.layout.new_view, this,false);

转载于:https://www.cnblogs.com/jiy-for-you/p/6916976.html

你可能感兴趣的文章
Spring中使用Velocity模板
查看>>
实现model中的文件上传FTP(一)
查看>>
MonkeyRecorder
查看>>
Maven概述
查看>>
页面多个Jquery版本共存的冲突问题,解决方法!
查看>>
BZOJ 2561 最小生成树
查看>>
上周热点回顾(8.18-8.24)
查看>>
「2012-12-30」Safe fonts, Google web fonts (Monda), Live-writer plugin & tips.
查看>>
原型,原型对象,原型链,构造函数,继承(一)
查看>>
UIButton和UIImageView的区别
查看>>
观察者模式
查看>>
文件的逻辑与物理结构
查看>>
【LeetCode】100. Same Tree-相同树
查看>>
第二冲刺阶段个人博客9
查看>>
Xamarin.iOS开发初体验
查看>>
cmd wevtutil 读取远程日志错误,Error:在没有配置的 DNS 服务器响应之后,名称 Server23.localdomain 的名称解析超时。...
查看>>
redis -list
查看>>
bzoj1798--维护序列--线段树
查看>>
Python3中的新特性(3)——代码迁移与2to3
查看>>
html基础
查看>>