/*
* Copyright 2015 Google Inc. All rights reserved.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.google.samples.apps.iosched.explore;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.util.Pair;
import android.support.v4.util.SparseArrayCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.samples.apps.iosched.R;
import com.google.samples.apps.iosched.archframework.ModelWithLoaderManager;
import com.google.samples.apps.iosched.archframework.PresenterImpl;
import com.google.samples.apps.iosched.archframework.UpdatableView;
import com.google.samples.apps.iosched.explore.ExploreIOModel.ExploreIOQueryEnum;
import com.google.samples.apps.iosched.explore.ExploreIOModel.ExploreIOUserActionEnum;
import com.google.samples.apps.iosched.explore.data.EventData;
import com.google.samples.apps.iosched.explore.data.ItemGroup;
import com.google.samples.apps.iosched.explore.data.LiveStreamData;
import com.google.samples.apps.iosched.explore.data.MessageData;
import com.google.samples.apps.iosched.explore.data.SessionData;
import com.google.samples.apps.iosched.injection.ModelProvider;
import com.google.samples.apps.iosched.provider.ScheduleContract;
import com.google.samples.apps.iosched.session.SessionDetailActivity;
import com.google.samples.apps.iosched.settings.ConfMessageCardUtils;
import com.google.samples.apps.iosched.settings.SettingsUtils;
import com.google.samples.apps.iosched.ui.widget.DrawShadowFrameLayout;
import com.google.samples.apps.iosched.ui.widget.recyclerview.ItemMarginDecoration;
import com.google.samples.apps.iosched.ui.widget.recyclerview.UpdatableAdapter;
import com.google.samples.apps.iosched.util.AccountUtils;
import com.google.samples.apps.iosched.util.ImageLoader;
import com.google.samples.apps.iosched.util.ThrottledContentObserver;
import com.google.samples.apps.iosched.util.TimeUtils;
import com.google.samples.apps.iosched.util.UIUtils;
import java.util.ArrayList;
import java.util.List;
import static android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import static com.google.samples.apps.iosched.settings.ConfMessageCardUtils.ConferencePrefChangeListener;
/**
* Display the Explore I/O cards. There are three styles of cards, which are referred to as Groups
* by the CollectionView implementation.
* <p/>
* <ul> <li>The live-streaming session cards.</li> <li>Time sensitive message cards.</li> <li>Session
* topic cards.</li> </ul>
* <p/>
* Only the final group of cards is dynamically loaded from a {@link
* android.content.ContentProvider}.
*/
public class ExploreIOFragment extends Fragment
implements UpdatableView<ExploreIOModel, ExploreIOQueryEnum, ExploreIOUserActionEnum> {
/**
* Used to load images asynchronously on a background thread.
*/
private ImageLoader mImageLoader;
/**
* RecyclerView containing a stream of cards to display to the user.
*/
private RecyclerView mCardList = null;
/**
* Adapter for providing data for the stream of cards.
*/
private ExploreAdapter mAdapter;
/**
* Empty view displayed when {@code mCardList} is empty.
*/
private View mEmptyView;
private List<UserActionListener> mListeners = new ArrayList<>();
private ThrottledContentObserver mSessionsObserver, mTagsObserver;
private ConferencePrefChangeListener mConfMessagesAnswerChangeListener =
new ConferencePrefChangeListener() {
@Override
protected void onPrefChanged(String key, boolean value) {
fireReloadEvent();
}
};
private OnSharedPreferenceChangeListener mSettingsChangeListener =
new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (SettingsUtils.PREF_DECLINED_WIFI_SETUP.equals(key)) {
fireReloadEvent();
} else if (AccountUtils.PREF_ACTIVE_ACCOUNT.equals(key)) {
fireReloadEvent();
}
}
};
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.explore_io_frag, container, false);
mCardList = (RecyclerView) root.findViewById(R.id.explore_card_list);
mCardList.setHasFixedSize(true);
final int cardVerticalMargin = getResources().getDimensionPixelSize(R.dimen.spacing_normal);
mCardList.addItemDecoration(new ItemMarginDecoration(0, cardVerticalMargin,
0, cardVerticalMargin));
mEmptyView = root.findViewById(android.R.id.empty);
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mImageLoader = new ImageLoader(getActivity(), R.drawable.io_logo);
initPresenter();
}
@Override
public void displayData(final ExploreIOModel model, final ExploreIOQueryEnum query) {
// Only display data when the tag metadata is available.
if (model.getTagMetadata() != null) {
if (mAdapter == null) {
mAdapter = new ExploreAdapter(getActivity(), model, mImageLoader);
mCardList.setAdapter(mAdapter);
} else {
mAdapter.update(model);
}
mEmptyView.setVisibility(mAdapter.getItemCount() > 0 ? View.GONE : View.VISIBLE);
}
}
@Override
public void displayErrorMessage(final ExploreIOQueryEnum query) {
// No UI changes when error with query
}
@Override
public void displayUserActionResult(final ExploreIOModel model,
final ExploreIOUserActionEnum userAction, final boolean success) {
switch (userAction) {
case RELOAD:
displayData(model, ExploreIOQueryEnum.SESSIONS);
break;
}
}
@Override
public Uri getDataUri(final ExploreIOQueryEnum query) {
switch (query) {
case SESSIONS:
return ScheduleContract.Sessions.CONTENT_URI;
default:
return Uri.EMPTY;
}
}
@Override
public Context getContext() {
return getActivity();
}
@Override
public void addListener(UserActionListener toAdd) {
mListeners.add(toAdd);
}
private void initPresenter() {
ExploreIOModel model = ModelProvider.provideExploreIOModel(
getDataUri(ExploreIOQueryEnum.SESSIONS), getContext(),
getLoaderManager());
PresenterImpl presenter = new PresenterImpl(model, this,
ExploreIOUserActionEnum.values(), ExploreIOQueryEnum.values());
presenter.loadInitialQueries();
}
@Override
public void onResume() {
super.onResume();
getActivity().invalidateOptionsMenu();
final DrawShadowFrameLayout drawShadowFrameLayout =
(DrawShadowFrameLayout) getActivity().findViewById(R.id.main_content);
if (drawShadowFrameLayout != null) {
// configure fragment's top clearance to take our overlaid Toolbar into account.
drawShadowFrameLayout.setShadowTopOffset(UIUtils.calculateActionBarSize(getActivity()));
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Register preference change listeners
ConfMessageCardUtils.registerPreferencesChangeListener(getContext(),
mConfMessagesAnswerChangeListener);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
sp.registerOnSharedPreferenceChangeListener(mSettingsChangeListener);
// Register content observers
mSessionsObserver = new ThrottledContentObserver(new ThrottledContentObserver.Callbacks() {
@Override
public void onThrottledContentObserverFired() {
fireReloadEvent();
fireReloadTagsEvent();
}
});
mTagsObserver = new ThrottledContentObserver(new ThrottledContentObserver.Callbacks() {
@Override
public void onThrottledContentObserverFired() {
fireReloadTagsEvent();
}
});
}
@Override
public void onDetach() {
super.onDetach();
if (mConfMessagesAnswerChangeListener != null) {
ConfMessageCardUtils.unregisterPreferencesChangeListener(getContext(),
mConfMessagesAnswerChangeListener);
}
if (mSettingsChangeListener != null) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
sp.unregisterOnSharedPreferenceChangeListener(mSettingsChangeListener);
}
getActivity().getContentResolver().unregisterContentObserver(mSessionsObserver);
getActivity().getContentResolver().unregisterContentObserver(mTagsObserver);
}
/**
* Let all UserActionListener know that the video list has been reloaded and that therefore we
* need to update the display of sessions.
*/
private void fireReloadEvent() {
if (!isAdded()) {
return;
}
for (UserActionListener h1 : mListeners) {
Bundle args = new Bundle();
args.putInt(ModelWithLoaderManager.KEY_RUN_QUERY_ID,
ExploreIOModel.ExploreIOQueryEnum.SESSIONS.getId());
h1.onUserAction(ExploreIOModel.ExploreIOUserActionEnum.RELOAD, args);
}
}
private void fireReloadTagsEvent() {
if (!isAdded()) {
return;
}
for (UserActionListener h1 : mListeners) {
Bundle args = new Bundle();
args.putInt(ModelWithLoaderManager.KEY_RUN_QUERY_ID,
ExploreIOModel.ExploreIOQueryEnum.TAGS.getId());
h1.onUserAction(ExploreIOModel.ExploreIOUserActionEnum.RELOAD, args);
}
}
/**
* Adapter for providing cards (Messages, Keynote, Live Stream and conference Tracks)
* for the Explore fragment.
*/
private static class ExploreAdapter
extends UpdatableAdapter<ExploreIOModel, RecyclerView.ViewHolder> {
private static final int TYPE_TRACK = 0;
private static final int TYPE_MESSAGE = 1;
private static final int TYPE_KEYNOTE = 2;
private static final int TYPE_LIVE_STREAM = 3;
private static final int TYPE_EVENT_DATA = 4;
private static final int LIVE_STREAM_TRACK_ID = R.string.live_now;
private static final int EVENT_DATA_TRACK_ID = 999;
// Immutable state
private final Activity mHost;
private final LayoutInflater mInflater;
private final ImageLoader mImageLoader;
private final RecyclerView.RecycledViewPool mRecycledViewPool;
// State
private List mItems;
// Maps of state keyed on track id
private SparseArrayCompat<UpdatableAdapter> mTrackSessionsAdapters;
private SparseArrayCompat<Parcelable> mTrackSessionsState;
ExploreAdapter(@NonNull Activity activity,
@NonNull ExploreIOModel model,
@NonNull ImageLoader imageLoader) {
mHost = activity;
mImageLoader = imageLoader;
mInflater = LayoutInflater.from(activity);
mRecycledViewPool = new RecyclerView.RecycledViewPool();
mItems = processModel(model);
setupSessionAdapters(model);
}
public void update(@NonNull ExploreIOModel model) {
// Attempt to update our data in-place so as not to lose scroll position etc.
final List newItems = processModel(model);
boolean changed = false;
if (newItems.size() != mItems.size()) {
changed = true;
} else {
for (int i = 0; i < newItems.size(); i++) {
final Object newCard = newItems.get(i);
final Object oldCard = mItems.get(i);
if (newCard.equals(oldCard)) {
if (newCard instanceof ItemGroup) {
final ItemGroup newTrack = (ItemGroup) newCard;
mTrackSessionsAdapters.get(getTrackId(newTrack))
.update(newTrack.getSessions());
}
} else {
changed = true;
break;
}
}
}
if (changed) {
// Couldn't update existing model, do a full refresh
mItems = newItems;
setupSessionAdapters(model);
notifyDataSetChanged();
}
}
@Override
public int getItemViewType(final int position) {
final Object item = mItems.get(position);
if (item instanceof LiveStreamData) {
return TYPE_LIVE_STREAM;
} else if (item instanceof ItemGroup) {
return TYPE_TRACK;
} else if (item instanceof MessageData) {
return TYPE_MESSAGE;
} else if (item instanceof SessionData) {
return TYPE_KEYNOTE;
} else if (item instanceof EventData) {
return TYPE_EVENT_DATA;
}
throw new IllegalArgumentException("Unknown view type.");
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent,
final int viewType) {
switch (viewType) {
case TYPE_EVENT_DATA:
return createEventViewHolder(parent);
case TYPE_TRACK:
return createTrackViewHolder(parent);
case TYPE_MESSAGE:
return createMessageViewHolder(parent);
case TYPE_KEYNOTE:
return createKeynoteViewHolder(parent);
case TYPE_LIVE_STREAM:
return createLiveStreamViewHolder(parent);
default:
throw new IllegalArgumentException("Unknown view type.");
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
switch (getItemViewType(position)) {
case TYPE_TRACK:
bindTrack((TrackViewHolder) holder, (ItemGroup) mItems.get(position));
break;
case TYPE_MESSAGE:
bindMessage((MessageViewHolder) holder, (MessageData) mItems.get(position));
break;
case TYPE_KEYNOTE:
bindKeynote((KeynoteViewHolder) holder, (SessionData) mItems.get(position));
break;
case TYPE_LIVE_STREAM:
bindLiveStream((TrackViewHolder) holder, (LiveStreamData) mItems.get(position));
break;
case TYPE_EVENT_DATA:
bindEventData((EventDataViewHolder) holder, (EventData) mItems.get(position));
break;
}
}
private void bindEventData(final EventDataViewHolder holder, final EventData eventData) {
int trackId = getTrackId(eventData);
holder.cards.setAdapter(mTrackSessionsAdapters.get(trackId));
holder.cards.getLayoutManager().onRestoreInstanceState(
mTrackSessionsState.get(trackId));
}
@Override
public void onViewRecycled(final RecyclerView.ViewHolder holder) {
if (holder instanceof TrackViewHolder) {
// Cache the scroll position of the session list so that we can restore it in onBind
final TrackViewHolder trackHolder = (TrackViewHolder) holder;
final int position = trackHolder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
final int trackId = getTrackId((ItemGroup) mItems.get(position));
mTrackSessionsState.put(trackId,
trackHolder.sessions.getLayoutManager().onSaveInstanceState());
}
}
super.onViewRecycled(holder);
}
@Override
public int getItemCount() {
return mItems.size();
}
private @NonNull
EventDataViewHolder createEventViewHolder(final ViewGroup parent) {
final EventDataViewHolder
holder = new EventDataViewHolder(
mInflater.inflate(R.layout.explore_io_event_card, parent, false));
holder.cards.setHasFixedSize(true);
holder.cards.setRecycledViewPool(mRecycledViewPool);
ViewCompat.setImportantForAccessibility(
holder.cards, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
holder.headerImage.setImageResource(R.drawable.explore_io_ontheground_header);
holder.title.setText(R.string.explore_io_on_the_ground_title);
return holder;
}
private @NonNull TrackViewHolder createTrackViewHolder(final ViewGroup parent) {
final TrackViewHolder holder = new TrackViewHolder(
mInflater.inflate(R.layout.explore_io_track_card, parent, false));
holder.sessions.setHasFixedSize(true);
holder.sessions.setRecycledViewPool(mRecycledViewPool);
ViewCompat.setImportantForAccessibility(
holder.sessions, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
holder.header.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final int position = holder.getAdapterPosition();
if (position == RecyclerView.NO_POSITION) return;
final ItemGroup track = (ItemGroup) mItems.get(position);
final Intent intent = new Intent(mHost, ExploreSessionsActivity.class);
intent.putExtra(ExploreSessionsActivity.EXTRA_FILTER_TAG, track.getId());
final ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation(mHost,
Pair.create((View) holder.headerImage, mHost.getString(
R.string.transition_track_header)),
Pair.create((View) holder.title, mHost.getString(
R.string.transition_track_title)),
Pair.create(holder.itemView, mHost.getString(
R.string.transition_track_background)));
ActivityCompat.startActivity(mHost, intent, options.toBundle());
}
});
return holder;
}
private @NonNull MessageViewHolder createMessageViewHolder(final ViewGroup parent) {
final MessageViewHolder holder = new MessageViewHolder(
mInflater.inflate(R.layout.explore_io_message_card, parent, false));
// Work with pre-existing infrastructure which supplied a click listener and relied on
// a shared pref listener & a reload to dismiss message cards.
// By setting our own click listener and manually calling onClick we can remove the
// item in the adapter directly.
holder.buttonStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final int position = holder.getAdapterPosition();
if (position == RecyclerView.NO_POSITION) return;
final MessageData message = (MessageData) mItems.get(position);
message.getStartButtonClickListener().onClick(holder.buttonStart);
mItems.remove(position);
notifyItemRemoved(position);
}
});
holder.buttonEnd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final int position = holder.getAdapterPosition();
if (position == RecyclerView.NO_POSITION) return;
final MessageData message = (MessageData) mItems.get(position);
message.getEndButtonClickListener().onClick(holder.buttonEnd);
mItems.remove(position);
notifyItemRemoved(position);
}
});
return holder;
}
private @NonNull KeynoteViewHolder createKeynoteViewHolder(final ViewGroup parent) {
final KeynoteViewHolder holder = new KeynoteViewHolder(
mInflater.inflate(R.layout.explore_io_keynote_card, parent, false));
holder.clickableItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final int position = holder.getAdapterPosition();
if (position == RecyclerView.NO_POSITION) return;
final SessionData keynote = (SessionData) mItems.get(position);
final Intent intent = new Intent(mHost, SessionDetailActivity.class);
intent.setData(
ScheduleContract.Sessions.buildSessionUri(keynote.getSessionId()));
final ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(mHost,
Pair.create(holder.itemView,
mHost.getString(
R.string.transition_session_background)),
Pair.create((View) holder.thumbnail,
mHost.getString(R.string.transition_session_image)));
ActivityCompat.startActivity(mHost, intent, options.toBundle());
}
});
return holder;
}
private @NonNull TrackViewHolder createLiveStreamViewHolder(final ViewGroup parent) {
final TrackViewHolder holder = new TrackViewHolder(
mInflater.inflate(R.layout.explore_io_track_card, parent, false));
ViewCompat.setImportantForAccessibility(
holder.sessions, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
holder.header.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final Intent intent = new Intent(mHost, ExploreSessionsActivity.class);
intent.setData(ScheduleContract.Sessions
.buildSessionsAfterUri(TimeUtils.getCurrentTime(mHost)));
intent.putExtra(ExploreSessionsActivity.EXTRA_SHOW_LIVE_STREAM_SESSIONS, true);
ActivityCompat.startActivity(mHost, intent, null);
}
});
return holder;
}
private void bindTrack(final TrackViewHolder holder, final ItemGroup track) {
bindTrackOrLiveStream(holder, track, track.getTitle());
}
private void bindMessage(final MessageViewHolder holder, final MessageData message) {
holder.description.setText(message.getMessageString(mHost));
if (message.getIconDrawableId() > 0) {
holder.icon.setVisibility(View.VISIBLE);
holder.icon.setImageResource(message.getIconDrawableId());
} else {
holder.icon.setVisibility(View.GONE);
}
if (message.getStartButtonStringResourceId() != -1) {
holder.buttonEnd.setVisibility(View.VISIBLE);
holder.buttonStart.setText(message.getStartButtonStringResourceId());
} else {
holder.buttonStart.setVisibility(View.GONE);
}
if (message.getEndButtonStringResourceId() != -1) {
holder.buttonEnd.setVisibility(View.VISIBLE);
holder.buttonEnd.setText(message.getEndButtonStringResourceId());
} else {
holder.buttonEnd.setVisibility(View.GONE);
}
}
private void bindKeynote(final KeynoteViewHolder holder, final SessionData keynote) {
holder.title.setText(keynote.getSessionName());
if (!TextUtils.isEmpty(keynote.getImageUrl())) {
mImageLoader.loadImage(keynote.getImageUrl(), holder.thumbnail);
}
if (!TextUtils.isEmpty(keynote.getDetails())) {
holder.description.setText(keynote.getDetails());
}
}
private void bindLiveStream(final TrackViewHolder holder, final LiveStreamData data) {
bindTrackOrLiveStream(holder, data, mHost.getString(R.string.live_now));
}
private void bindTrackOrLiveStream(final TrackViewHolder holder, final ItemGroup track,
final String title) {
holder.title.setText(title);
holder.header.setContentDescription(title);
if (track.getPhotoUrl() != null) {
holder.headerImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
mImageLoader.loadImage(track.getPhotoUrl(), holder.headerImage);
} else {
holder.headerImage.setScaleType(ImageView.ScaleType.FIT_CENTER);
holder.headerImage.setImageResource(R.drawable.ic_hash_io_16_monochrome);
}
final int trackId = getTrackId(track);
holder.sessions.setAdapter(mTrackSessionsAdapters.get(trackId));
holder.sessions.getLayoutManager().onRestoreInstanceState(
mTrackSessionsState.get(trackId));
}
/**
* Process the given {@link ExploreIOModel} to create the list of items to be displayed by
* the {@link RecyclerView}.
*/
private List processModel(final ExploreIOModel model) {
final ArrayList exploreCards = new ArrayList();
// Add any Message cards
final List<MessageData> messages = model.getMessages();
if (messages != null && !messages.isEmpty()) {
exploreCards.addAll(messages);
}
// Add Keynote card.
final SessionData keynote = model.getKeynoteData();
if (keynote != null) {
exploreCards.add(keynote);
}
// Add Event Cards if onsite.
if (SettingsUtils.isAttendeeAtVenue(mHost)) {
final EventData eventData = model.getEventData();
if (eventData != null && !eventData.getCards().isEmpty()) {
exploreCards.add(eventData);
}
}
// Add Live Stream card.
final LiveStreamData liveStream = model.getLiveStreamData();
if (liveStream != null && liveStream.getSessions().size() > 0) {
exploreCards.add(liveStream);
}
// Add track cards, ordered alphabetically
exploreCards.addAll(model.getOrderedTracks());
return exploreCards;
}
/**
* Setup adapters for tracks which have child session lists
*/
private void setupSessionAdapters(final ExploreIOModel model) {
final int trackCount = model.getOrderedTracks().size()
+ (model.getLiveStreamData() != null ? 1 : 0)
+ (model.getEventData() != null ? 1 : 0);
mTrackSessionsAdapters = new SparseArrayCompat<>(trackCount);
mTrackSessionsState = new SparseArrayCompat<>(trackCount);
final LiveStreamData liveStream = model.getLiveStreamData();
if (liveStream != null && liveStream.getSessions().size() > 0) {
mTrackSessionsAdapters.put(getTrackId(liveStream),
new LiveStreamSessionsAdapter(mHost, liveStream.getSessions(),
mImageLoader));
}
final EventData eventData = model.getEventData();
if (eventData != null && eventData.getCards() != null &&
eventData.getCards().size() > 0) {
mTrackSessionsAdapters.put(getTrackId(eventData),
new EventDataAdapter(mHost, eventData.getCards()));
}
for (final ItemGroup group : model.getOrderedTracks()) {
mTrackSessionsAdapters.put(getTrackId(group),
SessionsAdapter.createHorizontal(mHost, group.getSessions()));
}
}
/**
* A derived ID for each track; used as a key for some state objects
*/
private int getTrackId(Object track) {
if (track instanceof LiveStreamData) {
return LIVE_STREAM_TRACK_ID;
} else if (track instanceof EventData) {
return EVENT_DATA_TRACK_ID;
} else if (track instanceof ItemGroup) {
return ((ItemGroup)track).getId().hashCode();
}
return 0;
}
}
private static class EventDataViewHolder extends RecyclerView.ViewHolder {
final CardView card;
final ViewGroup header;
final ImageView headerImage;
final TextView title;
final RecyclerView cards;
public EventDataViewHolder(View itemView) {
super(itemView);
card = (CardView) itemView;
header = (ViewGroup) card.findViewById(R.id.header);
headerImage = (ImageView) card.findViewById(R.id.header_image);
title = (TextView) header.findViewById(R.id.title);
cards = (RecyclerView) card.findViewById(R.id.cards);
}
}
private static class TrackViewHolder extends RecyclerView.ViewHolder {
final CardView card;
final ViewGroup header;
final ImageView headerImage;
final TextView title;
final RecyclerView sessions;
public TrackViewHolder(View itemView) {
super(itemView);
card = (CardView) itemView;
header = (ViewGroup) card.findViewById(R.id.header);
headerImage = (ImageView) card.findViewById(R.id.header_image);
title = (TextView) header.findViewById(R.id.title);
sessions = (RecyclerView) card.findViewById(R.id.sessions);
}
}
private static class MessageViewHolder extends RecyclerView.ViewHolder {
final ImageView icon;
final TextView description;
final Button buttonStart;
final Button buttonEnd;
public MessageViewHolder(final View itemView) {
super(itemView);
icon = (ImageView) itemView.findViewById(R.id.icon);
description = (TextView) itemView.findViewById(R.id.description);
buttonStart = (Button) itemView.findViewById(R.id.buttonStart);
buttonEnd = (Button) itemView.findViewById(R.id.buttonEnd);
}
}
private static class KeynoteViewHolder extends RecyclerView.ViewHolder {
final ImageView thumbnail;
final TextView title;
final TextView description;
final ViewGroup clickableItem;
public KeynoteViewHolder(final View itemView) {
super(itemView);
thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
clickableItem = (ViewGroup) itemView.findViewById(R.id.explore_io_clickable_item);
}
}
}