机器人:设计的日历应用程序的视图 [英] Android: designing the view for a calendar app

查看:371
本文介绍了机器人:设计的日历应用程序的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为Android编写一个日历应用程序。日历需要一个有类似的默认应用程序,或者MS Outlook的一个星期显示:显示每个小时线一个网格,并显示为矩形约会

I'm writing a calendar application for Android. The calendar needs to a have a day display similar to the default application, or MS outlook: a grid showing a line for each hour, and the appointments shown as rectangles.

下面是从谷歌图片类似的样本图像:

Here's a similar sample image from Google Images:

在这里输入的形象描述

我下载的源$ C ​​$ C来自谷歌的Andr​​oid开源项目的日历应用程序,看到他们实施此显示作为Simplay的使用Canvas.drawRect()来绘制矩形的自定义视图,然后他们实施当用户点击自己的命中测试,看看被点击了其中的约会。

I downloaded the source code for the calendar app from Google's Android Open Source Project, and saw that they implemented this display as a custom view which simplay uses Canvas.drawRect() to draw the rectangles, and then they implemented their own hit-test when the user clicks, to see which appointment was clicked.

我已经写了一些东西,这对我自己和它的伟大工程,是不是太复杂了。

I already wrote some of that stuff on my own and it works great, and isn't too complicated.

问题是我需要的矩形内的文本(主题,时间)是链接到各种功能的不同的线路,我想知道我怎么能做到这一点。

The problem is that I need the different lines of text inside the rectangles (the subject, the time) to be links to various functionality, and I'm wondering how I can do that.

当我画画,我已经为每一个约会Rects。我想我可以在一个ArrayList为每一段文字,创造Rects为好,缓存所有这些,然后对缓存rects执行histt​​est。我只是怕这件事将是太重了...这听起来像一个坚实的设计?

When I draw, I already create Rects for each appointment. I was thinking I could create Rects for each piece of text as well, cache all of these in an ArrayList, and then perform the histtest against the cached rects. I'm only afraid this whole thing will be too heavy... does this sound like a solid design?

或者我应该避免自定义绘制干脆编程方式生成和(也许TextViews?)的地方的意见我是一个Android的新手,我不知道我的选择是......

Or should I avoid the custom drawing altogether and programmatically generate and place views (TextViews maybe?) I'm an Android novice and I'm not sure what my options are...

感谢您的帮助了!

推荐答案

好吧,作为宣布,在这里的一些例子:

Alright, as announced, here some example:

如果你只是使用自定义视图,你必须保持对象的列表,并自己绘制它们,而不是一个自定义布局,你只需要测量和布局的孩子们。因为你可以添加一个按钮,就没有必要使用命中测试或任何,因为如果你不弄乱观点只会收到的onClick()通话

If you just use a custom view, you have to keep lists of objects and draw them yourself, as opposed to a custom layout where you just have to measure and layout the children. Since you can just add a button, there's no need to use hit-tests or whatsoever, since if you don't mess up the view will just receive the onClick() call.

此外,您还可以轻松preVIEW在编辑器中你的布局,如果你正确地实现布局参数。这使得开发的的速度更快。

Also, you can easily preview your layout in the editor if you correctly implement layout parameters. Which makes development much faster.

例如。你可以定义自己的布局参数

E.g. you can define your own layout parameters

<resources>
    <declare-styleable name="TimeLineLayout_Layout">
        <attr name="time_from" format="string"/>
        <attr name="time_to" format="string"/>
    </declare-styleable>
</resources>

然后用它们像这样...

Then use them like this...

<com.github.bleeding182.timelinelayout.TimeLineLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#22662222">

    <TextView
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_green_dark"
        android:padding="8dp"
        android:text="12:00 - 16:00"
        app:time_from="12:00"
        app:time_to="16:00"/>

</com.github.bleeding182.timelinelayout.TimeLineLayout>

和结果会是这个样子(我知道这是丑陋的,但我做了这个只是用于测试:/)

And the result would look something like this (I know it's ugly, but I made this just for testing :/ )

日历视图

要做到这一点,您可以创建在那里你测量和布局的观点的基本布局。然后,您可以给您的布局,并通过从/到设定的时间和正确的测量/布点可以很容易地显示各种物品添加任何意见。

To do this, you create a basic layout where you measure and layout the views. You can then add any views to your layout, and by setting a time from / to and correctly measuring / layouting you can easily display all sorts of items.

在code的截图附在下面,的onDraw 将创建那些丑陋小时/半小时线。 onMeasure 是计算视图的高度和 onLayout 正在起草的意见,其正确的时间段。

The code for the screenshot is attached below, onDraw will create those ugly hour/half hour lines. onMeasure is for calculating view heights and onLayout is drawing the views to their correct time slot.

我希望这会有所帮助,它肯定比更容易在一个视图中处理一切使用。

I hope this helps, it's sure easier to use than handling everything in one view.

public class TimeLineLayout extends ViewGroup {

    private int tIntervalSpan = 24 * 60;
    private float mMeasuredMinuteHeight;

    public TimeLineLayout(Context context) {
        super(context);
    }

    public TimeLineLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TimeLineLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TimeLineLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
            if (layoutParams instanceof LayoutParams) {
                LayoutParams params = (LayoutParams) layoutParams;
                final int top = (int) (params.tFrom * mMeasuredMinuteHeight);
                child.layout(l, top, child.getMeasuredWidth(), top + child.getMeasuredHeight());
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));

        mMeasuredMinuteHeight = getMeasuredHeight() / (float) tIntervalSpan;

        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
            if (layoutParams instanceof LayoutParams) {
                LayoutParams params = (LayoutParams) layoutParams;
                child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) ((params.tTo - params.tFrom) * mMeasuredMinuteHeight), MeasureSpec.EXACTLY));
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        final float height = mMeasuredMinuteHeight * 60;
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        for(int i = 0; i < 24; i++) {
            paint.setStrokeWidth(2f);
            paint.setAlpha(255);
            canvas.drawLine(0, i * height, getMeasuredWidth(), i*height, paint);
            if(i < 23) {
                paint.setStrokeWidth(1f);
                paint.setAlpha(50);
                canvas.drawLine(0, i * height + 30 * mMeasuredMinuteHeight, getMeasuredWidth(), i * height + 30 * mMeasuredMinuteHeight, paint);
            }
        }
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    public static class LayoutParams extends ViewGroup.LayoutParams {

        private final int tFrom;
        private final int tTo;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.TimeLineLayout_Layout);
            final String from = a.getString(R.styleable.TimeLineLayout_Layout_time_from);
            final String to = a.getString(R.styleable.TimeLineLayout_Layout_time_to);
            a.recycle();
            tFrom = Integer.parseInt(from.split(":")[0]) * 60 + Integer.parseInt(from.split(":")[1]);
            tTo = Integer.parseInt(to.split(":")[0]) * 60 + Integer.parseInt(to.split(":")[1]);
        }
  }

这篇关于机器人:设计的日历应用程序的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆