Java tutorial
/* * Copyright 2014 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.ptapp.activity; import android.app.Activity; import android.app.Fragment; import android.app.LoaderManager; import android.content.Context; import android.content.CursorLoader; import android.content.Intent; import android.content.Loader; import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Parcelable; import android.preference.PreferenceManager; import android.provider.BaseColumns; import android.support.v4.view.ViewCompat; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.GenericRequestBuilder; import com.bumptech.glide.ListPreloader; import com.ptapp.provider.PTAppContract; import com.ptapp.provider.PTAppDatabase; import com.ptapp.app.R; //import com.ptapp.provider.ScheduleContract; import com.ptapp.widget.CollectionView; import com.ptapp.widget.CollectionViewCallbacks; import com.ptapp.widget.MessageCardView; import com.ptapp.utils.*; import com.squareup.picasso.Picasso; import java.text.DateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.TimeZone; import static com.ptapp.utils.LogUtils.*; /** * A {@link android.app.ListFragment} showing a list of sessions. The fragment arguments * indicate what is the list of sessions to show. It may be a set of tag * filters or a search query. */ public class SessionsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, CollectionViewCallbacks { private static final String TAG = makeLogTag(SessionsFragment.class); private static final String STATE_SESSION_QUERY_TOKEN = "session_query_token"; private static final String STATE_ARGUMENTS = "arguments"; /** * The handler message for updating the search query. */ private static final int MESSAGE_QUERY_UPDATE = 1; /** * The delay before actual requerying in millisecs. */ private static final int QUERY_UPDATE_DELAY_MILLIS = 100; /** * The number of rows ahead to preload images for */ private static final int ROWS_TO_PRELOAD = 2; private static final int ANIM_DURATION = 250; private static final int CARD_DISMISS_ACTION_DELAY = MessageCardView.ANIM_DURATION - 50; private Context mAppContext; // the cursor whose data we are currently displaying private int mSessionQueryToken; private Uri mCurrentUri = PTAppContract.ClassSubject.CONTENT_URI; private Cursor mCursor; private boolean mIsSearchCursor; // this variable is relevant when we start the sessions loader, and indicates the desired // behavior when load finishes: if true, this is a full reload (for example, because filters // have been changed); if not, it's just a refresh because data has changed. private boolean mSessionDataIsFullReload = false; private ImageLoader mImageLoader; private int mDefaultSessionColor; private CollectionView mCollectionView; private TextView mEmptyView; private View mLoadingView; //private TagMetadata mTagMetadata = null; private boolean mWasPaused = false; private static final int HERO_GROUP_ID = 123; private Bundle mArguments; private DateFormat mDateFormat = DateFormat.getDateInstance(DateFormat.SHORT); private DateFormat mTimeFormat = DateFormat.getTimeInstance(DateFormat.SHORT); private static final String CARD_ANSWER_ATTENDING_REMOTELY = "CARD_ANSWER_ATTENDING_REMOTELY"; private static final String CARD_ANSWER_ATTENDING_IN_PERSON = "CARD_ANSWER_ATTENDING_IN_PERSON"; private static final String CARD_ANSWER_YES = "CARD_ANSWER_YES"; private static final String CARD_ANSWER_NO = "CARD_ANSWER_NO"; private ThrottledContentObserver mSessionsObserver;//, mTagsObserver; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == MESSAGE_QUERY_UPDATE) { /*String query = (String) msg.obj; reloadFromArguments(BaseActivity.intentToFragmentArguments( new Intent(Intent.ACTION_SEARCH, PTAppContract.Courses.buildCourseUri(query))));*/ } } }; private Preloader mPreloader; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (mImageLoader == null) { mImageLoader = new ImageLoader(this.getActivity()); } mDefaultSessionColor = getResources().getColor(R.color.default_session_color); final TimeZone tz = SharedPrefUtil.getDisplayTimeZone(getActivity()); mDateFormat.setTimeZone(tz); mTimeFormat.setTimeZone(tz); if (savedInstanceState != null) { mSessionQueryToken = savedInstanceState.getInt(STATE_SESSION_QUERY_TOKEN); mArguments = savedInstanceState.getParcelable(STATE_ARGUMENTS); if (mArguments != null) { //mCurrentUri = mArguments.getParcelable("_uri"); } if (mSessionQueryToken > 0) { // Only if this is a config change should we initLoader(), to reconnect with an // existing loader. Otherwise, the loader will be init'd when reloadFromArguments // is called. getLoaderManager().initLoader(mSessionQueryToken, null, SessionsFragment.this); } } } public boolean canCollectionViewScrollUp() { return ViewCompat.canScrollVertically(mCollectionView, -1); } public void setContentTopClearance(int topClearance) { mCollectionView.setContentTopClearance(topClearance); } // Called when there is a change on sessions in the content provider private void onSessionsContentChanged() { LOGD(TAG, "ThrottledContentObserver fired (sessions). Content changed."); if (!isAdded()) { LOGD(TAG, "Ignoring ContentObserver event (Fragment not added)."); return; } LOGD(TAG, "Requesting sessions cursor reload as a result of ContentObserver firing."); reloadSessionData(false); } private void reloadSessionData(boolean fullReload) { LOGD(TAG, "Reloading session data: " + (fullReload ? "FULL RELOAD" : "light refresh")); mSessionDataIsFullReload = fullReload; getLoaderManager().restartLoader(mSessionQueryToken, mArguments, SessionsFragment.this); } @Override public void onPause() { super.onPause(); mWasPaused = true; } @Override public void onResume() { super.onResume(); if (mWasPaused) { mWasPaused = false; LOGD(TAG, "Reloading data as a result of onResume()"); mSessionsObserver.cancelPendingCallback(); reloadSessionData(false); } } public interface Callbacks { public void onSessionSelected(String sessionId, String courseName, String groupJid, int groupId, View clickedView); // public void onTagMetadataLoaded(TagMetadata metadata); } private static Callbacks sDummyCallbacks = new Callbacks() { @Override public void onSessionSelected(String sessionId, String courseName, String groupJid, int groupId, View clickedView) { } /* @Override public void onTagMetadataLoaded(TagMetadata metadata) { }*/ }; private Callbacks mCallbacks = sDummyCallbacks; private boolean useExpandedMode() { /*if (mCurrentUri != null && ScheduleContract.Sessions.CONTENT_URI.equals(mCurrentUri)) { // If showing all sessions (landing page) do not use expanded mode, // show info as condensed as possible return false; }*/ if (mCurrentUri != null && PTAppContract.ClassSubject.CONTENT_URI.equals(mCurrentUri)) { // If showing all sessions (landing page) do not use expanded mode, // show info as condensed as possible return false; } return true; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mAppContext = getActivity().getApplicationContext(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_sessions, container, false); mCollectionView = (CollectionView) root.findViewById(R.id.sessions_collection_view); mPreloader = new Preloader(ROWS_TO_PRELOAD); mCollectionView.setOnScrollListener(mPreloader); mEmptyView = (TextView) root.findViewById(R.id.empty_text); mLoadingView = root.findViewById(R.id.loading); return root; } void reloadFromArguments(Bundle arguments) { // Load new arguments if (arguments == null) { arguments = new Bundle(); } else { // since we might make changes, don't meddle with caller's copy arguments = (Bundle) arguments.clone(); } // save arguments so we can reuse it when reloading from content observer events mArguments = arguments; LOGD(TAG, "SessionsFragment reloading from arguments: " + arguments); mCurrentUri = arguments.getParcelable("_uri"); if (mCurrentUri == null) { // if no URI, default to all sessions URI /*LOGD(TAG, "SessionsFragment did not get a URL, defaulting to all sessions.");*/ LOGD(TAG, "Setting uri to teacher's all groups..."); arguments.putParcelable("_uri", PTAppContract.StaffEngagement.CONTENT_STAFF_GROUPS_URI); mCurrentUri = PTAppContract.StaffEngagement.CONTENT_STAFF_GROUPS_URI; } /*if (ScheduleContract.Sessions.isSearchUri(mCurrentUri)) { mSessionQueryToken = SessionsQuery.SEARCH_TOKEN; } else {*/ mSessionQueryToken = SessionsQuery.NORMAL_TOKEN; /*}*/ //LOGD(TAG, "SessionsFragment reloading, uri=" + mCurrentUri + ", expanded=" + useExpandedMode()); reloadSessionData(true); // full reload } void requestQueryUpdate(String query) { mHandler.removeMessages(MESSAGE_QUERY_UPDATE); mHandler.sendMessageDelayed(Message.obtain(mHandler, MESSAGE_QUERY_UPDATE, query), QUERY_UPDATE_DELAY_MILLIS); } @Override public void onAttach(Activity activity) { super.onAttach(activity); if (!(activity instanceof Callbacks)) { throw new ClassCastException("Activity must implement fragment's callbacks."); } mAppContext = getActivity().getApplicationContext(); mCallbacks = (Callbacks) activity; mSessionsObserver = new ThrottledContentObserver(new ThrottledContentObserver.Callbacks() { @Override public void onThrottledContentObserverFired() { onSessionsContentChanged(); } }); /*activity.getContentResolver().registerContentObserver( PTAppContract.Courses.CONTENT_URI, true, mSessionsObserver);*/ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(activity); sp.registerOnSharedPreferenceChangeListener(mPrefChangeListener); } @Override public void onDetach() { super.onDetach(); mCallbacks = sDummyCallbacks; getActivity().getContentResolver().unregisterContentObserver(mSessionsObserver); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); sp.unregisterOnSharedPreferenceChangeListener(mPrefChangeListener); } public void animateReload() { //int curTop = mCollectionView.getTop(); mCollectionView.setAlpha(0); //mCollectionView.setTop(getResources().getDimensionPixelSize(R.dimen.browse_sessions_anim_amount)); //mCollectionView.animate().y(curTop).alpha(1).setDuration(ANIM_DURATION).setInterpolator(new DecelerateInterpolator()); mCollectionView.animate().alpha(1).setDuration(ANIM_DURATION).setInterpolator(new DecelerateInterpolator()); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(STATE_SESSION_QUERY_TOKEN, mSessionQueryToken); outState.putParcelable(STATE_ARGUMENTS, mArguments); } // LoaderCallbacks interface @Override public Loader<Cursor> onCreateLoader(int id, Bundle data) { LOGD(TAG, "onCreateLoader, id=" + id + ", data=" + data); final Intent intent = BaseActivity.fragmentArgumentsToIntent(data); Uri sessionsUri = intent.getData(); if ((id == SessionsQuery.NORMAL_TOKEN || id == SessionsQuery.SEARCH_TOKEN) && sessionsUri == null) { LOGD(TAG, "intent.getData() is null, setting to default sessions search"); /*sessionsUri = ScheduleContract.Sessions.CONTENT_URI;*/ /*sessionsUri = PTAppContract.ClassSubject.CONTENT_URI;*/ sessionsUri = PTAppContract.StaffEngagement.CONTENT_STAFF_GROUPS_URI; } Loader<Cursor> loader = null; //Log.d(TAG, "teacherId onCreateLoader: " + SharedPrefUtil.getPrefTeacherUserId(getActivity())); String selectionWhere = PTAppContract.StaffEngagement.STAFF_ID + " = ?"; /*String[] selectionArgs = new String[]{SharedPrefUtil.getPrefTeacherUserId(getActivity())};*/ //TODO:get the staff ID from the sharedPref. String[] selectionArgs = new String[] { String.valueOf(2) }; if (id == SessionsQuery.NORMAL_TOKEN) { LOGD(TAG, "Creating educator loader for " + sessionsUri + ", selectionWhere " + selectionWhere); loader = new CursorLoader(getActivity(), sessionsUri, SessionsQuery.NORMAL_PROJECTION, selectionWhere, selectionArgs, null); /*loader = new CursorLoader(getActivity(), sessionsUri, SessionsQuery.NORMAL_PROJECTION, selectionWhere, selectionArgs, PTAppContract.Courses.SORT_BY_COURSE_NAME);*/ } return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { if (getActivity() == null) { return; } int token = loader.getId(); LOGD(TAG, "Loader finished: " + (token == SessionsQuery.NORMAL_TOKEN ? "educator" : token == SessionsQuery.SEARCH_TOKEN ? "search" : "")); if (token == SessionsQuery.NORMAL_TOKEN || token == SessionsQuery.SEARCH_TOKEN) { if (mCursor != null && mCursor != cursor) { mCursor.close(); } mCursor = cursor; mIsSearchCursor = token == SessionsQuery.SEARCH_TOKEN; LOGD(TAG, "Cursor has " + mCursor.getCount() + " items. Will now update collection view."); updateCollectionView(); } else { LOGD(TAG, "Query complete, Not Actionable: " + token); cursor.close(); } } @Override public void onLoaderReset(Loader<Cursor> loader) { } private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sp, String key) { if (isAdded()) { if (SharedPrefUtil.PREF_LOCAL_TIMES.equals(key)) { updateCollectionView(); } else if (SharedPrefUtil.PREF_ATTENDEE_AT_VENUE.equals(key)) { if (mCursor != null) { reloadSessionData(true); } } } } }; private void updateCollectionView() { if (mCursor == null) { LOGD(TAG, "updateCollectionView: not ready yet... no cursor."); // not ready! return; } LOGD(TAG, "SessionsFragment updating CollectionView... " + (mSessionDataIsFullReload ? "(FULL RELOAD)" : "(light refresh)")); mCursor.moveToPosition(-1); int itemCount = mCursor.getCount(); mMaxDataIndexAnimated = 0; CollectionView.Inventory inv; if (itemCount == 0) { showEmptyView(); inv = new CollectionView.Inventory(); } else { hideEmptyView(); inv = prepareInventory(); } Parcelable state = null; if (!mSessionDataIsFullReload) { // it's not a full reload, so we want to keep scroll position, etc state = mCollectionView.onSaveInstanceState(); } LOGD(TAG, "Updating CollectionView with inventory, # groups = " + inv.getGroupCount() + " total items = " + inv.getTotalItemCount()); mCollectionView.setCollectionAdapter(this); mCollectionView.updateInventory(inv, mSessionDataIsFullReload); if (state != null) { mCollectionView.onRestoreInstanceState(state); } mSessionDataIsFullReload = false; } private void hideEmptyView() { mEmptyView.setVisibility(View.GONE); mLoadingView.setVisibility(View.GONE); } private void showEmptyView() { /*final String searchQuery = PTAppContract.Courses.isSearchUri(mCurrentUri) ? PTAppContract.Courses.getSearchQuery(mCurrentUri) : null;*/ if (mCurrentUri.equals(PTAppContract.ClassSubject.CONTENT_URI)) { // if showing all sessions, the empty view should say "loading..." because // the only reason we would have no sessions at all is if we are currently // preparing the database from the bootstrap data, which should only take a few // seconds. mEmptyView.setVisibility(View.GONE); mLoadingView.setVisibility(View.VISIBLE); } /*else if (ScheduleContract.Sessions.isUnscheduledSessionsInInterval(mCurrentUri)) { // Showing sessions in a given interval, so say "No sessions in this time slot." mEmptyView.setText(R.string.no_matching_sessions_in_interval); mEmptyView.setVisibility(View.VISIBLE); mLoadingView.setVisibility(View.GONE); } else if (ScheduleContract.Sessions.isSearchUri(mCurrentUri) && (TextUtils.isEmpty(searchQuery) || "*".equals(searchQuery))) { // Empty search query (for example, user hasn't started to type the query yet), // so don't show an empty view. mEmptyView.setText(""); mEmptyView.setVisibility(View.VISIBLE); mLoadingView.setVisibility(View.GONE); }*/ /*else { // Showing sessions as a result of search or filter, so say "No matching sessions." mEmptyView.setText(R.string.no_matching_sessions); mEmptyView.setVisibility(View.VISIBLE); mLoadingView.setVisibility(View.GONE); }*/ } // Creates the CollectionView groups based on the cursor data. private CollectionView.Inventory prepareInventory() { LOGD(TAG, "Preparing collection view inventory."); ArrayList<CollectionView.InventoryGroup> pastGroups = new ArrayList<CollectionView.InventoryGroup>(); ArrayList<CollectionView.InventoryGroup> futureGroups = new ArrayList<CollectionView.InventoryGroup>(); HashMap<String, CollectionView.InventoryGroup> pastGroupsByName = new HashMap<String, CollectionView.InventoryGroup>(); HashMap<String, CollectionView.InventoryGroup> futureGroupsByName = new HashMap<String, CollectionView.InventoryGroup>(); CollectionView.InventoryGroup heroGroup = null; mCursor.moveToPosition(-1); int nextGroupId = HERO_GROUP_ID + 1000; // to avoid conflict with the special hero group ID LOGD(TAG, "Total cursor data items: " + mCursor.getCount()); int dataIndex = -1; final long now = UIUtils.getCurrentTime(mAppContext); final boolean conferenceEnded = TimeUtils.hasConferenceEnded(mAppContext); LOGD(TAG, "conferenceEnded=" + conferenceEnded); final boolean expandedMode = useExpandedMode(); /*final int displayCols = getResources().getInteger(expandedMode ? R.integer.explore_2nd_level_grid_columns : R.integer.explore_1st_level_grid_columns);*/ final int displayCols = 2; LOGD(TAG, "Using " + displayCols + " columns."); mPreloader.setDisplayCols(displayCols); while (mCursor.moveToNext()) { // For each data item, we decide what group it should appear under, then // we add it to that group (and create the group if it doesn't exist yet). /*long sessionEnd = mCursor.getLong(mCursor.getColumnIndex( ScheduleContract.Sessions.SESSION_END));*/ long sessionEnd = 0; ++dataIndex; /*boolean showAsPast = !conferenceEnded && sessionEnd < now;*/ boolean showAsPast = false; //for PTApp, it's a teacher status text/tagline String groupLabel = "Placeholder to show teacher's status text/tagline..."; /*if (expandedMode) { String tags = mCursor.getString(mCursor.getColumnIndex(ScheduleContract.Sessions.SESSION_TAGS)); TagMetadata.Tag groupTag = tags == null ? null : mTagMetadata.getSessionGroupTag(tags.split(",")); if (groupTag != null) { groupLabel = groupTag.getName(); } else { groupLabel = getString(R.string.others); } groupLabel += (showAsPast ? " (" + getString(R.string.session_finished) + ")" : ""); } else { groupLabel = showAsPast ? getString(R.string.ended_sessions) : ""; }*/ /*LOGV(TAG, "Data item #" + dataIndex + ", sessionEnd=" + sessionEnd + ", groupLabel=" + groupLabel + " showAsPast=" + showAsPast);*/ CollectionView.InventoryGroup group; // should this item be the hero group? //In this PTApp we dont need to show the top-most single column(full width), so /*if (!useExpandedMode() && !showAsPast && heroGroup == null) { // yes, this item is the hero LOGV(TAG, "This item is the hero."); group = heroGroup = new CollectionView.InventoryGroup(HERO_GROUP_ID) .setDisplayCols(1) // hero item spans all columns .setShowHeader(false).setHeaderLabel(""); } else {*/ // "list" and "map" are just shorthand variables pointing to the right list and map ArrayList<CollectionView.InventoryGroup> list = showAsPast ? pastGroups : futureGroups; HashMap<String, CollectionView.InventoryGroup> map = showAsPast ? pastGroupsByName : futureGroupsByName; // Create group, if it doesn't exist yet if (!map.containsKey(groupLabel)) { LOGV(TAG, "Creating new group: " + groupLabel); group = new CollectionView.InventoryGroup(nextGroupId++).setDisplayCols(displayCols) .setShowHeader(false).setHeaderLabel(groupLabel); map.put(groupLabel, group); list.add(group); } else { LOGV(TAG, "Adding to existing group: " + groupLabel); group = map.get(groupLabel); } //} // add this item to the group LOGV(TAG, "...adding to group '" + groupLabel + "' with custom data index " + dataIndex); group.addItemWithCustomDataIndex(dataIndex); } // prepare the final groups list ArrayList<CollectionView.InventoryGroup> groups = new ArrayList<CollectionView.InventoryGroup>(); if (heroGroup != null) { groups.add(heroGroup); // start with the hero } groups.addAll(futureGroups); // then all future events groups.addAll(pastGroups); // then all past events LOGD(TAG, "Total: hero " + (heroGroup == null ? "absent" : "present") + " " + futureGroups.size() + " future groups, " + " " + pastGroups.size() + " past groups, total " + groups.size()); // the first group doesn't need a header label, because it's the "default group" //if (groups.size() > 0) { // groups.get(0).setHeaderLabel("").setShowHeader(false); //} // finally, assemble the inventory and we're done CollectionView.Inventory inventory = new CollectionView.Inventory(); for (CollectionView.InventoryGroup g : groups) { inventory.addGroup(g); } return inventory; } @Override public View newCollectionHeaderView(Context context, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); return inflater.inflate(R.layout.list_item_explore_header, parent, false); } @Override public void bindCollectionHeaderView(Context context, View view, int groupId, String groupLabel) { TextView tv = (TextView) view.findViewById(android.R.id.text1); if (tv != null) { tv.setText(groupLabel); } } @Override public View newCollectionItemView(Context context, int groupId, ViewGroup parent) { final LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); int layoutId; /*if (useExpandedMode()) { layoutId = R.layout.list_item_session; } else { // Group HERO_GROUP_ID is the hero -- use a larger layout layoutId = (groupId == HERO_GROUP_ID) ? R.layout.list_item_session_hero : R.layout.list_item_session_summarized; }*/ layoutId = R.layout.list_item_session_summarized; return inflater.inflate(layoutId, parent, false); } private StringBuilder mBuffer = new StringBuilder(); private int mMaxDataIndexAnimated = 0; @Override public void bindCollectionItemView(Context context, View view, final int groupId, int indexInGroup, int dataIndex, Object tag) { if (mCursor == null || !mCursor.moveToPosition(dataIndex)) { LOGW(TAG, "Can't bind collection view item, dataIndex=" + dataIndex + (mCursor == null ? ": cursor is null" : ": bad data index.")); return; } Log.v(TAG, "test collection view cursor data: " + mCursor.getString(0) + ", " + mCursor.getString(1) + ", " + mCursor.getString(2) + ", " + mCursor.getString(3) + ", "); final String groupJid = mCursor.getString(SessionsQuery.GROUP_JID); final String classSubjectId = mCursor.getString(SessionsQuery.CLASS_SUBJECT_ID); if (classSubjectId == null) { return; } // first, read session info from cursor and put it in convenience variables final String courseTitle = mCursor.getString(SessionsQuery.GROUP_NAME); /*final String courseTitle = mCursor.getString(SessionsQuery.SUBJECT_TITLE); final String className = mCursor.getString(SessionsQuery.CLASS_TITLE) + "-" + mCursor.getString(SessionsQuery.SECTION_TITLE);*/ /*final String educatorId = mCursor.getString(SessionsQuery.EDUCATOR_ID); final String classId = mCursor.getString(SessionsQuery.CLASS_ID); final String studentId = mCursor.getString(SessionsQuery.STUDENT_ID);*/ /*final String sessionAbstract = mCursor.getString(SessionsQuery.ABSTRACT); final long sessionStart = mCursor.getLong(SessionsQuery.SESSION_START); final long sessionEnd = mCursor.getLong(SessionsQuery.SESSION_END); final String roomName = mCursor.getString(SessionsQuery.ROOM_NAME); int sessionColor = mCursor.getInt(SessionsQuery.COLOR);*/ int sessionColor = 0; sessionColor = sessionColor == 0 ? getResources().getColor(R.color.default_session_color) : sessionColor; /*final String snippet = mIsSearchCursor ? mCursor.getString(SessionsQuery.SNIPPET) : null; final Spannable styledSnippet = mIsSearchCursor ? buildStyledSnippet(snippet) : null; final boolean starred = mCursor.getInt(SessionsQuery.IN_MY_SCHEDULE) != 0; final String[] tags = mCursor.getString(SessionsQuery.TAGS).split(",");*/ // now let's compute a few pieces of information from the data, which we will use // later to decide what to render where /*final boolean hasLivestream = !TextUtils.isEmpty(mCursor.getString( SessionsQuery.LIVESTREAM_URL));*/ final long now = UIUtils.getCurrentTime(context); /*final boolean happeningNow = now >= sessionStart && now <= sessionEnd;*/ // text that says "LIVE" if session is live, or empty if session is not live /*final String liveNowText = hasLivestream ? " " + UIUtils.getLiveBadgeText(context, sessionStart, sessionEnd) : "";*/ final String liveNowText = ""; // get reference to all the views in the layout we will need final TextView titleView = (TextView) view.findViewById(R.id.session_title); final TextView subtitleView = (TextView) view.findViewById(R.id.session_subtitle); final TextView shortSubtitleView = (TextView) view.findViewById(R.id.session_subtitle_short); /*final TextView snippetView = (TextView) view.findViewById(R.id.session_snippet);*/ final TextView abstractView = (TextView) view.findViewById(R.id.session_abstract); final TextView categoryView = (TextView) view.findViewById(R.id.session_category); final View boxView = view.findViewById(R.id.info_box); final View sessionTargetView = view.findViewById(R.id.session_target); final View grpmsgView = (ImageView) view.findViewById(R.id.session_grp_msg); if (sessionColor == 0) { // use default sessionColor = mDefaultSessionColor; } sessionColor = UIUtils.scaleSessionColorToDefaultBG(sessionColor); ImageView photoView = (ImageView) view.findViewById(R.id.session_photo_colored); if (photoView != null) { if (!mPreloader.isDimensSet()) { final ImageView finalPhotoView = photoView; photoView.post(new Runnable() { @Override public void run() { mPreloader.setDimens(finalPhotoView.getWidth(), finalPhotoView.getHeight()); } }); } // colored photoView.setColorFilter(UIUtils.setColorAlpha(sessionColor, UIUtils.SESSION_PHOTO_SCRIM_ALPHA)); } else { photoView = (ImageView) view.findViewById(R.id.session_photo); } ((BaseActivity) getActivity()).getLPreviewUtils().setViewName(photoView, "photo_" + classSubjectId); // when we load a photo, it will fade in from transparent so the // background of the container must be the session color to avoid a white flash ViewParent parent = photoView.getParent(); if (parent != null && parent instanceof View) { ((View) parent).setBackgroundColor(sessionColor); } else { photoView.setBackgroundColor(sessionColor); } //String photo = mCursor.getString(SessionsQuery.PHOTO_URL); int subjPath = R.drawable.nophotoavailable; //TODO:Temporary task to generate screenshots if (courseTitle != null) { if (courseTitle.contains("English")) { subjPath = R.drawable.logo_english; } else if (courseTitle.contains("Math")) { subjPath = R.drawable.logo_math; } else if (courseTitle.contains("Punjabi")) { subjPath = R.drawable.course_punjabi; } else if (courseTitle.contains("Hindi")) { subjPath = R.drawable.course_hindi; } else if (courseTitle.contains("German")) { subjPath = R.drawable.course_german; } else if (courseTitle.contains("Dutch")) { subjPath = R.drawable.course_dutch; } else if (courseTitle.contains("Science")) { subjPath = R.drawable.course_science; } else if (courseTitle.contains("French")) { subjPath = R.drawable.course_french; } } /*if (!TextUtils.isEmpty(photo)) {*/ //mImageLoader.loadImage(photo, photoView, true /*crop*/); Picasso.with(context) // .load(subjPath) // .placeholder(CommonConstants.LOADING) // .error(CommonConstants.ERROR_IMAGE) // .fit() // .into(photoView); /*} else { // cleaning the (potentially) recycled photoView, in case this session has no photo: photoView.setImageDrawable(null); }*/ // render title /*titleView.setText(courseTitle == null ? "?" : courseTitle);*/ titleView.setText(courseTitle == null ? "?" : courseTitle); // render subtitle into either the subtitle view, or the short subtitle view, as available if (subtitleView != null) { /*subtitleView.setText(UIUtils.formatSessionSubtitle( sessionStart, sessionEnd, roomName, mBuffer, context) + liveNowText);*/ //subtitleView.setText(className == null ? "?" : className); } else if (shortSubtitleView != null) { //Dummy data /*shortSubtitleView.setText("25");*/ shortSubtitleView.setText(mCursor.getString(SessionsQuery.MEMBER_COUNT)); shortSubtitleView.setGravity(Gravity.RIGHT); /*shortSubtitleView.setText(UIUtils.formatSessionSubtitle( sessionStart, sessionEnd, roomName, mBuffer, context, true) + liveNowText);*/ //shortSubtitleView.setText(className == null ? "?" : className); } // render category if (categoryView != null) { /*categoryView.setText(className == null ? "?" : className);*/ } // if a snippet view is available, render the session snippet there. /*if (snippetView != null) { *//*if (mIsSearchCursor) { // render the search snippet into the snippet view snippetView.setText(styledSnippet); } else { // render speaker names and abstracts into the snippet view mBuffer.setLength(0); if (!TextUtils.isEmpty(speakerNames)) { mBuffer.append(speakerNames).append(". "); } if (!TextUtils.isEmpty(sessionAbstract)) { mBuffer.append(sessionAbstract); } snippetView.setText(mBuffer.toString()); }*//* }*/ if (abstractView != null && !mIsSearchCursor) { // render speaker names and abstracts into the abstract view mBuffer.setLength(0); /*if (!TextUtils.isEmpty(speakerNames)) { mBuffer.append(speakerNames).append("\n\n"); } if (!TextUtils.isEmpty(sessionAbstract)) { mBuffer.append(sessionAbstract); }*/ abstractView.setText(mBuffer.toString()); } // in expanded mode, the box background color follows the session color if (useExpandedMode()) { boxView.setBackgroundColor(sessionColor); } /*// show or hide the "in my schedule" indicator view.findViewById(R.id.indicator_in_schedule).setVisibility(starred ? View.VISIBLE : View.INVISIBLE);*/ // if we are in condensed mode and this card is the hero card (big card at the top // of the screen), set up the message card if necessary. if (!useExpandedMode() && groupId == HERO_GROUP_ID) { // this is the hero view, so we might want to show a message card final boolean cardShown = setupMessageCard(view); // if this is the wide hero layout, show or hide the card or the session abstract // view, as appropriate (they are mutually exclusive). final View cardContainer = view.findViewById(R.id.message_card_container_wide); final View abstractContainer = view.findViewById(R.id.session_abstract); if (cardContainer != null && abstractContainer != null) { cardContainer.setVisibility(cardShown ? View.VISIBLE : View.GONE); abstractContainer.setVisibility(cardShown ? View.GONE : View.VISIBLE); abstractContainer.setBackgroundColor(sessionColor); } } // if this session is live right now, display the "LIVE NOW" icon on top of it View liveNowBadge = view.findViewById(R.id.live_now_badge); if (liveNowBadge != null) { liveNowBadge.setVisibility(View.INVISIBLE); //liveNowBadge.setVisibility(happeningNow && hasLivestream ? View.VISIBLE : View.GONE); } // if this view is clicked, open the session details view final View finalPhotoView = photoView; final int studentGroupId = mCursor.getInt(SessionsQuery.GROUP_ID); sessionTargetView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCallbacks.onSessionSelected(classSubjectId, courseTitle, groupJid, studentGroupId, finalPhotoView); } }); // animate this card if (dataIndex > mMaxDataIndexAnimated) { mMaxDataIndexAnimated = dataIndex; } //if this view is clicked, open group messages chatting screen if (grpmsgView != null) { grpmsgView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i(TAG, "grp msg image clicked, opening group messages screen"); Intent intent = new Intent(getActivity(), EducatorGroupMsgActivity.class); startActivity(intent); } }); } } private boolean setupMessageCard(View hero) { MessageCardView card = (MessageCardView) hero.findViewById(R.id.message_card); if (card == null) { LOGE(TAG, "Message card not found in UI (R.id.message_card)."); return false; } /*if (!PrefUtils.hasAnsweredLocalOrRemote(getActivity()) && !TimeUtils.hasConferenceEnded(getActivity())) { // show the "in person" vs "remote" card setupLocalOrRemoteCard(card); return true; } else if (WiFiUtils.shouldOfferToSetupWifi(getActivity(), true)) { // show wifi setup card setupWifiOfferCard(card); return true; } else if (PrefUtils.shouldOfferIOExtended(getActivity(), true)) { // show the I/O extended card setupIOExtendedCard(card); return true;*/ // } else { card.setVisibility(View.GONE); return false; } } /*private void setupLocalOrRemoteCard(final MessageCardView card) { card.overrideBackground(R.drawable.card_bg); card.setText(getString(R.string.question_local_or_remote)); card.setButton(0, getString(R.string.attending_remotely), CARD_ANSWER_ATTENDING_REMOTELY, false, 0); card.setButton(1, getString(R.string.attending_in_person), CARD_ANSWER_ATTENDING_IN_PERSON, true, 0); final Context context = getActivity().getApplicationContext(); final Activity activity = getActivity(); card.setListener(new MessageCardView.OnMessageCardButtonClicked() { @Override public void onMessageCardButtonClicked(final String tag) { final boolean inPerson = CARD_ANSWER_ATTENDING_IN_PERSON.equals(tag); card.dismiss(true); if (activity != null) { Toast.makeText(activity, inPerson ? R.string.explore_attending_in_person_toast : R.string.explore_attending_remotely_toast, Toast.LENGTH_LONG).show(); } // post delayed to give card time to animate mHandler.postDelayed(new Runnable() { @Override public void run() { PrefUtils.setAttendeeAtVenue(context, inPerson); PrefUtils.markAnsweredLocalOrRemote(context); } }, CARD_DISMISS_ACTION_DELAY); } }); card.show(); }*/ /*private void setupWifiOfferCard(final MessageCardView card) { card.overrideBackground(R.drawable.card_bg); card.setText(getString(TimeUtils.hasConferenceStarted(getActivity()) ? R.string.question_setup_wifi_after_i_o_start : R.string.question_setup_wifi_before_i_o_start)); card.setButton(0, getString(R.string.no_thanks), CARD_ANSWER_NO, false, 0); card.setButton(1, getString(R.string.setup_wifi_yes), CARD_ANSWER_YES, true, 0); final Context context = getActivity().getApplicationContext(); card.setListener(new MessageCardView.OnMessageCardButtonClicked() { @Override public void onMessageCardButtonClicked(final String tag) { card.dismiss(true); // post delayed to give card time to animate mHandler.postDelayed(new Runnable() { @Override public void run() { if (CARD_ANSWER_YES.equals(tag)) { WiFiUtils.showWiFiDialog(SessionsFragment.this.getActivity()); } else { PrefUtils.markDeclinedWifiSetup(context); } } }, CARD_DISMISS_ACTION_DELAY); } }); card.show(); } */ /* private void setupIOExtendedCard(final MessageCardView card) { card.overrideBackground(R.drawable.card_bg); card.setText(getString(R.string.question_i_o_extended)); card.setButton(0, getString(R.string.no_thanks), CARD_ANSWER_NO, false, 0); card.setButton(1, getString(R.string.browse_events), CARD_ANSWER_YES, true, 0); final Context context = getActivity().getApplicationContext(); card.setListener(new MessageCardView.OnMessageCardButtonClicked() { @Override public void onMessageCardButtonClicked(final String tag) { card.dismiss(true); // post delayed to give card time to animate mHandler.postDelayed(new Runnable() { @Override public void run() { if (CARD_ANSWER_YES.equals(tag)) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Config.IO_EXTENDED_LINK)); startActivity(intent); } PrefUtils.markDismissedIOExtendedCard(SessionsFragment.this.getActivity()); } }, CARD_DISMISS_ACTION_DELAY); } }); card.show(); } */ private void animateSessionAppear(final View view) { } private class Preloader extends ListPreloader<String> { private int[] photoDimens; private int displayCols; public Preloader(int maxPreload) { super(maxPreload); } public void setDisplayCols(int displayCols) { this.displayCols = displayCols; } public boolean isDimensSet() { return photoDimens != null; } public void setDimens(int width, int height) { if (photoDimens == null) { photoDimens = new int[] { width, height }; } } @Override protected int[] getDimensions(String s) { return photoDimens; } @Override protected List<String> getItems(int start, int end) { // Our start and end are rows, we need to adjust them into data columns // The keynote is 1 row with 1 data item, so we need to adjust. int keynoteDataOffset = (displayCols - 1); int dataStart = start * displayCols - keynoteDataOffset; int dataEnd = end * displayCols - keynoteDataOffset; List<String> urls = new ArrayList<String>(); if (mCursor != null) { for (int i = dataStart; i < dataEnd; i++) { if (mCursor.moveToPosition(i)) { /*urls.add(mCursor.getString(SessionsQuery.PHOTO_URL));*/ } } } return urls; } @Override protected GenericRequestBuilder getRequestBuilder(String url) { return mImageLoader.beginImageLoad(url, null, true /*crop*/); } } /** * {@lin com.google.samples.apps.iosched.provider.ScheduleContract.Sessions} * query parameters. */ private interface SessionsQuery { int NORMAL_TOKEN = 0x1; int SEARCH_TOKEN = 0x3; //Need to specify the table names alongwith column names, to avoid ambiguity error in 'SELECT' statement String[] NORMAL_PROJECTION = { PTAppDatabase.Tables.DEFAULT_GROUPS + "." + BaseColumns._ID, PTAppContract.DefaultGroups.GROUP_NAME, PTAppDatabase.Tables.DEFAULT_GROUPS + "." + PTAppContract.DefaultGroups.JID, PTAppDatabase.Tables.DEFAULT_GROUPS + "." + PTAppContract.DefaultGroups.CLASS_SUBJECT_ID, PTAppDatabase.Tables.DEFAULT_GROUPS + "." + PTAppContract.DefaultGroups.MEMBER_COUNT /*PTAppDatabase.Tables.STAFF_ENGAGEMENT + "." + PTAppContract.StaffEngagement.CLASS_SUBJECT_ID, PTAppContract.Classes.CLASS_TYPE_CODE, PTAppContract.Classes.SECTION_TYPE_CODE, PTAppContract.Subject.DESCRIPTION, PTAppDatabase.Tables.CLASS_SUBJECT + "." + PTAppContract.ClassSubject.GROUP_JID*/ }; int GROUP_ID = 0; int GROUP_NAME = 1; int GROUP_JID = 2; int CLASS_SUBJECT_ID = 3; int MEMBER_COUNT = 4; /*int CLASS_SUBJECT_ID = 0; int CLASS_TITLE = 1; int SECTION_TITLE = 2; int SUBJECT_TITLE = 3; int GROUP_JID = 4;*/ } //private static final int TAG_METADATA_TOKEN = 0x4; }