1
0
Fork 0
mirror of https://github.com/MatomoCamp/matomocamp-companion-android.git synced 2024-09-19 16:13:46 +02:00

Added EventDetailsFragment and Activity

Renamed AbstractAsyncTaskLoader to LocalCacheLoader
This commit is contained in:
Christophe Beyls 2013-12-29 03:43:14 +01:00
parent f9747078f6
commit c1204d8f17
28 changed files with 485 additions and 22 deletions

View file

@ -35,6 +35,7 @@
android:value=".activities.TextSearchResultActivity" />
</activity>
<activity android:name=".activities.TrackScheduleActivity" />
<activity android:name=".activities.EventDetailsActivity" />
<activity
android:name=".activities.TextSearchResultActivity"
android:launchMode="singleTop" >

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@color/translucent_fosdem_purple" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:drawable="@drawable/abc_list_focused_holo" android:state_focused="true" android:state_pressed="false"/>
<item android:drawable="@drawable/pressed_background" android:state_pressed="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:textIsSelectable="true"
android:textSize="22sp" />
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:textIsSelectable="true"
android:textSize="16sp" />
<TextView
android:id="@+id/persons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:textIsSelectable="true"
android:textSize="14sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:background="@color/fosdem_purple"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:id="@+id/track"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_small_labels"
android:drawablePadding="5dp"
android:textColor="@android:color/white"
android:textIsSelectable="true"
android:textSize="14sp" />
<TextView
android:id="@+id/time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_small_time"
android:drawablePadding="5dp"
android:textColor="@android:color/white"
android:textIsSelectable="true"
android:textSize="14sp" />
<TextView
android:id="@+id/room"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_small_place"
android:drawablePadding="5dp"
android:textColor="@android:color/white"
android:textIsSelectable="true"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/abstract_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/translucent_grey"
android:padding="5dp"
android:textIsSelectable="true" />
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true" />
<LinearLayout
android:id="@+id/links_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone" >
<TextView
android:id="@+id/links_label"
style="@style/HeaderStyle"
android:layout_marginTop="16dp"
android:text="@string/related_links_header" />
<View
android:id="@+id/links_label_line"
style="@style/HeaderLineStyle" />
</LinearLayout>
</LinearLayout>
</ScrollView>

8
res/layout/item_link.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_background"
android:padding="10dp"
android:textSize="16sp" />

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/listDivider" />

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="fosdem_purple">#9c3381</color>
<color name="translucent_fosdem_purple">#dd9c3381</color>
<color name="main_menu_background">#f0fafafa</color>
<color name="current_section_background">#29000000</color>
<color name="translucent_grey">#29000000</color>
<color name="background_tab_pressed">#6633B5E5</color>

View file

@ -17,6 +17,8 @@
<string name="developer_room">Developer room</string>
<string name="lightning_talk">Lightning talk</string>
<string name="certification_exam">Certification Exam</string>
<string name="event_details">Event details</string>
<string name="related_links_header">RELATED LINKS</string>
<string name="search_events">Search events</string>
<string name="search_settings_description">Events</string>
<string name="search_hint">Event, track, person</string>

View file

@ -2,4 +2,21 @@
<style name="AppTheme" parent="@style/Theme.AppCompat.Light"></style>
<style name="HeaderStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">5dp</item>
<item name="android:paddingLeft">5dp</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/fosdem_purple</item>
</style>
<style name="HeaderLineStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">1dp</item>
<item name="android:layout_marginBottom">5dp</item>
<item name="android:background">@color/fosdem_purple</item>
</style>
</resources>

View file

@ -0,0 +1,43 @@
package be.digitalia.fosdem.activities;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import be.digitalia.fosdem.R;
import be.digitalia.fosdem.fragments.EventDetailsFragment;
import be.digitalia.fosdem.model.Event;
public class EventDetailsActivity extends ActionBarActivity {
public static final String EXTRA_EVENT = "event";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content);
Event event = getIntent().getParcelableExtra(EXTRA_EVENT);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle(R.string.event_details);
bar.setSubtitle(event.getTrack().toString());
if (savedInstanceState == null) {
Fragment f = EventDetailsFragment.newInstance(event);
getSupportFragmentManager().beginTransaction().add(R.id.content, f).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return false;
}
}

View file

@ -45,7 +45,7 @@ import be.digitalia.fosdem.fragments.MapFragment;
import be.digitalia.fosdem.fragments.MessageDialogFragment;
import be.digitalia.fosdem.fragments.PersonsListFragment;
import be.digitalia.fosdem.fragments.TracksFragment;
import be.digitalia.fosdem.loaders.AbstractAsyncTaskLoader;
import be.digitalia.fosdem.loaders.LocalCacheLoader;
public class MainActivity extends ActionBarActivity implements ListView.OnItemClickListener, Handler.Callback {
@ -315,7 +315,7 @@ public class MainActivity extends ActionBarActivity implements ListView.OnItemCl
getSupportLoaderManager().initLoader(DOWNLOAD_SCHEDULE_LOADER_ID, null, downloadScheduleLoaderCallbacks);
}
private static class DownloadScheduleLoader extends AbstractAsyncTaskLoader<Integer> {
private static class DownloadScheduleLoader extends LocalCacheLoader<Integer> {
public DownloadScheduleLoader(Context context) {
super(context);
@ -370,7 +370,7 @@ public class MainActivity extends ActionBarActivity implements ListView.OnItemCl
public MainMenuAdapter(LayoutInflater inflater) {
this.inflater = inflater;
currentSectionBackgroundColor = getResources().getColor(R.color.current_section_background);
currentSectionBackgroundColor = getResources().getColor(R.color.translucent_grey);
}
@Override

View file

@ -12,8 +12,8 @@ import be.digitalia.fosdem.model.Track;
public class TrackScheduleActivity extends ActionBarActivity {
public static final String ARG_DAY = "day";
public static final String ARG_TRACK = "track";
public static final String EXTRA_DAY = "day";
public static final String EXTRA_TRACK = "track";
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -21,8 +21,8 @@ public class TrackScheduleActivity extends ActionBarActivity {
setContentView(R.layout.content);
Bundle extras = getIntent().getExtras();
Day day = extras.getParcelable(ARG_DAY);
Track track = extras.getParcelable(ARG_TRACK);
Day day = extras.getParcelable(EXTRA_DAY);
Track track = extras.getParcelable(EXTRA_TRACK);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);

View file

@ -0,0 +1,234 @@
package be.digitalia.fosdem.fragments;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import be.digitalia.fosdem.R;
import be.digitalia.fosdem.db.DatabaseManager;
import be.digitalia.fosdem.loaders.LocalCacheLoader;
import be.digitalia.fosdem.model.Event;
import be.digitalia.fosdem.model.Link;
import be.digitalia.fosdem.model.Person;
import be.digitalia.fosdem.utils.DateUtils;
import be.digitalia.fosdem.utils.StringUtils;
public class EventDetailsFragment extends Fragment {
private static class EventDetails {
List<Person> persons;
List<Link> links;
}
private static class ViewHolder {
LayoutInflater inflater;
TextView personsTextView;
ViewGroup linksContainer;
}
private static final int EVENT_DETAILS_LOADER_ID = 1;
private static final String ARG_EVENT = "event";
private static final DateFormat TIME_DATE_FORMAT = DateUtils.getTimeDateFormat();
private Event event;
private ViewHolder holder;
public static EventDetailsFragment newInstance(Event event) {
EventDetailsFragment f = new EventDetailsFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_EVENT, event);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
event = getArguments().getParcelable(ARG_EVENT);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_event_details, container, false);
holder = new ViewHolder();
holder.inflater = inflater;
((TextView) view.findViewById(R.id.title)).setText(event.getTitle());
TextView textView = (TextView) view.findViewById(R.id.subtitle);
String text = event.getSubTitle();
if (TextUtils.isEmpty(text)) {
textView.setVisibility(View.GONE);
} else {
textView.setText(text);
}
// Set the persons summary text first; replace it with the clickable text when the loader completes
holder.personsTextView = (TextView) view.findViewById(R.id.persons);
holder.personsTextView.setText(event.getPersonsSummary());
((TextView) view.findViewById(R.id.track)).setText(event.getTrack().getName());
Date startTime = event.getStartTime();
Date endTime = event.getEndTime();
text = String.format("%1$s, %2$s - %3$s", event.getDay().toString(), (startTime != null) ? TIME_DATE_FORMAT.format(startTime) : "?",
(endTime != null) ? TIME_DATE_FORMAT.format(endTime) : "?");
((TextView) view.findViewById(R.id.time)).setText(text);
((TextView) view.findViewById(R.id.room)).setText(event.getRoomName());
MovementMethod movementMethod = LinkMovementMethod.getInstance();
textView = (TextView) view.findViewById(R.id.abstract_text);
text = event.getAbstractText();
if (TextUtils.isEmpty(text)) {
textView.setVisibility(View.GONE);
} else {
textView.setText(StringUtils.trimEnd(Html.fromHtml(text)));
textView.setMovementMethod(movementMethod);
}
textView = (TextView) view.findViewById(R.id.description);
text = event.getDescription();
if (TextUtils.isEmpty(text)) {
textView.setVisibility(View.GONE);
} else {
textView.setText(StringUtils.trimEnd(Html.fromHtml(text)));
textView.setMovementMethod(movementMethod);
}
holder.linksContainer = (ViewGroup) view.findViewById(R.id.links_container);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
holder = null;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(EVENT_DETAILS_LOADER_ID, null, eventDetailsLoaderCallbacks);
}
private static class EventDetailsLoader extends LocalCacheLoader<EventDetails> {
private final Event event;
public EventDetailsLoader(Context context, Event event) {
super(context);
this.event = event;
}
@Override
public EventDetails loadInBackground() {
EventDetails result = new EventDetails();
DatabaseManager dbm = DatabaseManager.getInstance();
result.persons = dbm.getPersons(event);
result.links = dbm.getLinks(event);
return result;
}
}
private final LoaderCallbacks<EventDetails> eventDetailsLoaderCallbacks = new LoaderCallbacks<EventDetails>() {
@Override
public Loader<EventDetails> onCreateLoader(int id, Bundle args) {
return new EventDetailsLoader(getActivity(), event);
}
@Override
public void onLoadFinished(Loader<EventDetails> loader, EventDetails data) {
// 1. Persons
if (data.persons != null) {
// Build a list of clickable persons
SpannableStringBuilder sb = new SpannableStringBuilder();
int length = 0;
for (Person person : data.persons) {
if (length != 0) {
sb.append(", ");
}
String name = person.getName();
sb.append(name);
length = sb.length();
sb.setSpan(new PersonClickableSpan(person), length - name.length(), length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
holder.personsTextView.setText(sb);
}
// 2. Links
// Keep the first 2 views in links container (titles) only
int linkViewCount = holder.linksContainer.getChildCount();
if (linkViewCount > 2) {
holder.linksContainer.removeViews(2, linkViewCount - 2);
}
if ((data.links != null) && (data.links.size() > 0)) {
holder.linksContainer.setVisibility(View.VISIBLE);
for (Link link : data.links) {
View view = holder.inflater.inflate(R.layout.item_link, holder.linksContainer, false);
TextView tv = (TextView) view.findViewById(R.id.description);
tv.setText(link.getDescription());
view.setOnClickListener(new LinkClickListener(link));
holder.linksContainer.addView(view);
// Add a list divider
view = holder.inflater.inflate(R.layout.list_divider, holder.linksContainer, false);
holder.linksContainer.addView(view);
}
} else {
holder.linksContainer.setVisibility(View.GONE);
}
}
@Override
public void onLoaderReset(Loader<EventDetails> loader) {
}
};
private static class PersonClickableSpan extends ClickableSpan {
private final Person person;
public PersonClickableSpan(Person person) {
this.person = person;
}
@Override
public void onClick(View v) {
// TODO Launch the person details activity
}
}
private static class LinkClickListener implements View.OnClickListener {
private final Link link;
public LinkClickListener(Link link) {
this.link = link;
}
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link.getUrl()));
v.getContext().startActivity(intent);
}
}
}

View file

@ -1,10 +1,9 @@
package be.digitalia.fosdem.fragments;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Typeface;
import android.os.Bundle;
@ -22,6 +21,7 @@ import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import be.digitalia.fosdem.R;
import be.digitalia.fosdem.activities.EventDetailsActivity;
import be.digitalia.fosdem.db.DatabaseManager;
import be.digitalia.fosdem.loaders.SimpleCursorLoader;
import be.digitalia.fosdem.model.Day;
@ -108,13 +108,14 @@ public class TrackScheduleListFragment extends ListFragment implements LoaderCal
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO
Event event = adapter.getItem(position);
Intent intent = new Intent(getActivity(), EventDetailsActivity.class).putExtra(EventDetailsActivity.EXTRA_EVENT, event);
startActivity(intent);
}
private static class TrackScheduleAdapter extends CursorAdapter {
private static final DateFormat START_TIME_DATE_FORMAT = DateUtils.withBelgiumTimeZone(SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT,
Locale.getDefault()));
private static final DateFormat TIME_DATE_FORMAT = DateUtils.getTimeDateFormat();
private final LayoutInflater inflater;
private final int titleTextSize;
@ -149,7 +150,7 @@ public class TrackScheduleListFragment extends ListFragment implements LoaderCal
ViewHolder holder = (ViewHolder) view.getTag();
Event event = DatabaseManager.toEvent(cursor, holder.event);
holder.event = event;
holder.time.setText(START_TIME_DATE_FORMAT.format(event.getStartTime()));
holder.time.setText(TIME_DATE_FORMAT.format(event.getStartTime()));
String eventTitle = event.getTitle();
String personsSummary = event.getPersonsSummary();

View file

@ -96,8 +96,8 @@ public class TracksListFragment extends ListFragment implements LoaderCallbacks<
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Track track = adapter.getItem(position);
Intent intent = new Intent(getActivity(), TrackScheduleActivity.class).putExtra(TrackScheduleActivity.ARG_DAY, day).putExtra(
TrackScheduleActivity.ARG_TRACK, track);
Intent intent = new Intent(getActivity(), TrackScheduleActivity.class).putExtra(TrackScheduleActivity.EXTRA_DAY, day).putExtra(
TrackScheduleActivity.EXTRA_TRACK, track);
startActivity(intent);
}

View file

@ -3,11 +3,11 @@ package be.digitalia.fosdem.loaders;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
public abstract class AbstractAsyncTaskLoader<T> extends AsyncTaskLoader<T> {
public abstract class LocalCacheLoader<T> extends AsyncTaskLoader<T> {
private T mResult;
public AbstractAsyncTaskLoader(Context context) {
public LocalCacheLoader(Context context) {
super(context);
}

View file

@ -88,7 +88,7 @@ public class Event implements Parcelable {
}
public String getUrl() {
return FosdemUrls.getPerson(slug);
return FosdemUrls.getEvent(slug);
}
public String getTitle() {

View file

@ -1,18 +1,26 @@
package be.digitalia.fosdem.utils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
public class DateUtils {
private static final TimeZone belgiumTimeZone = TimeZone.getTimeZone("GMT+1");
private static final TimeZone BELGIUM_TIME_ZONE = TimeZone.getTimeZone("GMT+1");
private static final DateFormat TIME_DATE_FORMAT = withBelgiumTimeZone(SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT, Locale.getDefault()));
public static TimeZone getBelgiumTimeZone() {
return belgiumTimeZone;
return BELGIUM_TIME_ZONE;
}
public static DateFormat withBelgiumTimeZone(DateFormat format) {
format.setTimeZone(belgiumTimeZone);
format.setTimeZone(BELGIUM_TIME_ZONE);
return format;
}
public static DateFormat getTimeDateFormat() {
return TIME_DATE_FORMAT;
}
}

View file

@ -1,5 +1,6 @@
package be.digitalia.fosdem.utils;
public class StringUtils {
/**
* Mirror of the unicode table from 00c0 to 017f without diacritics.
@ -31,4 +32,18 @@ public class StringUtils {
public static String toSlug(String source) {
return removeDiacritics(source).replace(" ", "");
}
public static CharSequence trimEnd(CharSequence source) {
final int length = source.length();
int pos = length - 1;
while (Character.isWhitespace(source.charAt(pos))) {
pos--;
}
pos++;
if (pos == length) {
// No whitespace found at the end
return source;
}
return source.subSequence(0, pos);
}
}