web-dev-qa-db-ja.com

材料-カレンダービューは日付の背景色を設定します

私の目標は、配列に基づいてカレンダービューでさまざまな日付をマークできるAndroidライブラリを見つけることです。日付は連続している場合と連続していない場合があります。私の理想的なシナリオは、各日付の背景色。重大な問題は、サーバークエリから取得されるため、実行時までこの色がわからないことです。

私はこれを一日中研究してきましたが、私の最高の希望は_material-calendarview_( github )のようです。しかし、私は彼らのコードがやや侵入不可能であることに気づいています。それは私にありますが、私は完全に立ち往生しています。

XMLレイアウトに次のようなカレンダーを追加しました。

_<com.prolificinteractive.materialcalendarview.MaterialCalendarView
        Android:id="@+id/calendar_view"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_marginLeft="20dp"
        Android:layout_marginRight="20dp"
        xmlns:app="http://schemas.Android.com/apk/res-auto"
        app:mcv_showOtherDates="all"
        app:mcv_selectionColor="#00F"/>
_

そして、私のアクティビティでは、次のインスタンス変数があります。

_private MaterialCalendarView calendarView;
private ArrayList<Date> markedDates;
_

そして私のonCreateView()のこのコード

_calendarView = (MaterialCalendarView) view.findViewById(R.id.calendar_view);
_

わかりました、簡単です。しかし、日付の配列からカレンダーにマークを付ける方法がわかりません。私はこの方法に取り組んでいますが、ここにあるものを超えて進む方法がわかりません。

_private void initializeCalendar() {

        calendarView.setOnDateChangedListener(context);
        calendarView.setShowOtherDates(MaterialCalendarView.SHOW_ALL);

        Calendar calendar = Calendar.getInstance();
        calendarView.setSelectedDate(calendar.getTime());

        calendar.set(calendar.get(Calendar.YEAR), Calendar.JANUARY, 1);
        calendarView.setMinimumDate(calendar.getTime());

        calendar.set(calendar.get(Calendar.YEAR), Calendar.DECEMBER, 31);
        calendarView.setMaximumDate(calendar.getTime());

        int bgColor = sharedVisualElements.getPrimaryColor();

        calendarView.addDecorators(new EventDecorator(bgColor, ????));
}
_

その最後の行は、この内部クラスを参照しています。

_private class EventDecorator implements DayViewDecorator {

        private final int color;
        private final HashSet<CalendarDay> dates;

        public EventDecorator(int color, Collection<CalendarDay> dates) {
            this.color = color;
            this.dates = new HashSet<>(dates);
        }

        @Override
        public boolean shouldDecorate(CalendarDay day) {
            return dates.contains(day);
        }

        @Override
        public void decorate(DayViewFacade view) {
            view.addSpan(new DotSpan(5, color));
        }
    }
_

私の_ArrayList<Date> markedDates_を彼らが_Collection<CalendarDay> dates_と呼ぶものに変換するという私の挑戦だと思います。同意しますか?しかし、これは私が本当に行き詰まっているところです。この データ構造 は私には奇妙です。 new CalendarDay()を呼び出してインスタンス化しようとすると、クラスはすぐに約10個の新しいメソッドで展開されますが、それらの役割や処理方法がわかりません。明らかに、私はRailsここに行きます。これほどトリッキーになることはできません。

誰かがこの目的のためにこのライブラリを使用し、このタスクを実行する方法を知っていますか?私はひどく止まっています。また、実行時にのみ認識される色を使用して背景色を設定できる、より単純なライブラリがあれば、私はすべての耳です。

助けてくれてありがとう。私はこれを紛らわしい方法で書いたのではないかと心配しています。これは私が完全に混乱しているという事実の結果です。

10
AndroidDev

選択した背景色をプログラムで変更する場合は、次の方法を使用します。-

MaterialCalendarView materialCalendar = (MaterialCalendarView)findViewById(R.id.materialCalenderView);
materialCalendar.setSelectionColor(Color.parseColor("#00BCD4"));

このコードを使用すると、すべてのセレクターが同じ色になるため、条件に応じて異なるカラーセレクターを使用する場合は、decorator()を使用します。

4
Mrinmoy

私はこれを解決したので、他の誰かが同じ質問をする場合に備えて、その解決策を投稿します。より効率的な方法がある場合は、解決策として投稿してください。

日付のリストを含む配列があると言いました。私がする必要があるのは、その配列を反復処理し、各Dateを適切な年、月、日に設定されたCalendarオブジェクトに変換してから、そのオブジェクトを別のArrayListに追加することです。今回はArrayList<CalendarDay>。例えば:

List<CalendarDay> list = new ArrayList<CalendarDay>();
Calendar calendar = Calendar.getInstance();

for (Date date : markedDates) {
    // might be a more elegant way to do this part, but this is very explicit
    int year = date.getYear();
    int month = date.getMonthOfYear() - 1; // months are 0-based in Calendar
    int day = date.getDayOfMonth();

    calendar.set(year, month, day);
    CalendarDay calendarDay = CalendarDay.from(calendar);
    list.add(calendarDay);
}

これで、このCalendarDayオブジェクトのリストができましたが、まだ十分ではありません。データ構造を作成する最後のステップは、これをOPで苦労していたと述べたものに「変換」することです-a Collection<CalendarDay>構造。ここに着いたら、これはこれ以上簡単なことではないことがわかりました。次のように割り当てるだけです。

calendarDays = list;

そして、デコレータを追加したいときは、すべて準備ができています。これを行うだけです:

calendarView.addDecorators(new EventDecorator(myColor, calendarDays));

もう1つ言及する必要があり、これが私の混乱の主な原因でした。これをインスタンス化する方法がわかりませんでしたCollection<CalendarDay>オブジェクト。インスタンス変数セクション(コンストラクターの前)のずっと上に、このコードを追加しました。そのほとんどすべてがAndroid Studioに入力されました:

private Collection<CalendarDay> calendarDays = new Collection<CalendarDay>() {
        @Override
        public boolean add(CalendarDay object) {
            return false;
        }

        @Override
        public boolean addAll(Collection<? extends CalendarDay> collection) {
            return false;
        }

        @Override
        public void clear() {

        }

        @Override
        public boolean contains(Object object) {
            return false;
        }

        @Override
        public boolean containsAll(Collection<?> collection) {
            return false;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        @NonNull
        @Override
        public Iterator<CalendarDay> iterator() {
            return null;
        }

        @Override
        public boolean remove(Object object) {
            return false;
        }

        @Override
        public boolean removeAll(Collection<?> collection) {
            return false;
        }

        @Override
        public boolean retainAll(Collection<?> collection) {
            return false;
        }

        @Override
        public int size() {
            return 0;
        }

        @NonNull
        @Override
        public Object[] toArray() {
            return new Object[0];
        }

        @NonNull
        @Override
        public <T> T[] toArray(T[] array) {
            return null;
        }
    };

これが誰かに役立つことを願っています。繰り返しますが、より良い解決策がある場合は、投稿してください。私のものを削除します。

4
AndroidDev

HashSetの代わりにArrayListを使用したのはなぜですか?コレクションをインスタンス化できない理由は、コレクションがインターフェイスであるため、匿名クラスを作成してメソッドをオーバーライドする必要があったためです。

これが私が似たようなことをした方法です:

このメソッドは、2つのCalendarオブジェクトを受け取り、2つのCalendar日付の間のすべての日をCalendarDaysのHashSetに追加します。

private HashSet<CalendarDay> getCalendarDaysSet(Calendar cal1, Calendar cal2) {
    HashSet<CalendarDay> setDays = new HashSet<>();
    while (cal1.getTime().before(cal2.getTime())) {
        CalendarDay calDay = CalendarDay.from(cal1);
        setDays.add(calDay);
        cal1.add(Calendar.DATE, 1);
    }

    return setDays;
}

onCreateView(...)メソッドで、2つのカレンダーの日付を動的に設定しましたが、その差はHashSetに格納されます。ただし、HashSetで独自のランダムな日付のセットを渡すことができます。

Calendar cal1 = Calendar.getInstance();
    cal1.set(2016, 8, 1);
    Calendar cal2 = Calendar.getInstance();
    cal2.set(2016, 9, 1);

    HashSet<CalendarDay> setDays = getCalendarDaysSet(cal1, cal2);
    int myColor = R.color.red;
    mCalendarView.addDecorator(new BookingDecorator(myColor, setDays));

私の場合、BookingDecoratorはDayViewDecoratorインターフェースを実装するクラスです。

 private class BookingDecorator implements DayViewDecorator {
    private int mColor;
    private HashSet<CalendarDay> mCalendarDayCollection;

    public BookingDecorator(int color, HashSet<CalendarDay> calendarDayCollection) {
        mColor = color;
        mCalendarDayCollection = calendarDayCollection;
    }

    @Override
    public boolean shouldDecorate(CalendarDay day) {
        return mCalendarDayCollection.contains(day);
    }

    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new ForegroundColorSpan(mColor));
        //view.addSpan(new BackgroundColorSpan(Color.BLUE));
        view.setBackgroundDrawable(ContextCompat.getDrawable(getContext(),R.drawable.greenbox));

    }
}

あなたの投稿はとても役に立ちました。私が誰かを助けてくれることを願っています。

3
Sameer Khanal