diff --git a/commons/res/layout/detail_category_item.xml b/commons/res/layout/detail_category_item.xml
index 385d13ddb..0c1e47a90 100644
--- a/commons/res/layout/detail_category_item.xml
+++ b/commons/res/layout/detail_category_item.xml
@@ -1,12 +1,22 @@
-
+
+
+
+
diff --git a/commons/res/layout/detail_main_panel.xml b/commons/res/layout/detail_main_panel.xml
deleted file mode 100644
index 2a321f856..000000000
--- a/commons/res/layout/detail_main_panel.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/commons/res/layout/fragment_media_detail.xml b/commons/res/layout/fragment_media_detail.xml
index b1d566acd..0ca84aa2f 100644
--- a/commons/res/layout/fragment_media_detail.xml
+++ b/commons/res/layout/fragment_media_detail.xml
@@ -28,14 +28,137 @@
android:scaleType="fitCenter"
/>
-
+ android:cacheColorHint="@android:color/transparent">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/commons/res/values/strings.xml b/commons/res/values/strings.xml
index 2612a795e..664de8594 100644
--- a/commons/res/values/strings.xml
+++ b/commons/res/values/strings.xml
@@ -138,5 +138,7 @@
Categories
Loading...
None selected
+ No description
+ Unknown license
Campaigns
diff --git a/commons/src/main/java/org/wikimedia/commons/media/MediaDetailFragment.java b/commons/src/main/java/org/wikimedia/commons/media/MediaDetailFragment.java
index 4e084822b..cf0c79db4 100644
--- a/commons/src/main/java/org/wikimedia/commons/media/MediaDetailFragment.java
+++ b/commons/src/main/java/org/wikimedia/commons/media/MediaDetailFragment.java
@@ -2,7 +2,6 @@ package org.wikimedia.commons.media;
import android.content.Intent;
import android.graphics.*;
-import android.net.Uri;
import android.os.*;
import android.text.*;
import android.util.Log;
@@ -10,15 +9,12 @@ import android.util.TypedValue;
import android.view.*;
import android.widget.*;
import com.actionbarsherlock.app.SherlockFragment;
-import com.android.volley.toolbox.NetworkImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;
import com.android.volley.toolbox.*;
-import org.mediawiki.api.ApiResult;
-import org.mediawiki.api.MWApi;
import org.wikimedia.commons.*;
import java.io.IOException;
@@ -54,19 +50,20 @@ public class MediaDetailFragment extends SherlockFragment {
private ProgressBar loadingProgress;
private ImageView loadingFailed;
private MediaDetailSpacer spacer;
- private int initialListIndex = 0;
private int initialListTop = 0;
private TextView title;
private TextView desc;
private TextView license;
- private ListView listView;
+ private LinearLayout categoryContainer;
+ private ScrollView scrollView;
private ArrayList categoryNames;
private boolean categoriesLoaded = false;
private boolean categoriesPresent = false;
- private ArrayAdapter categoryAdapter;
- private ViewTreeObserver.OnGlobalLayoutListener observer; // for layout stuff, only used once!
+ private ViewTreeObserver.OnGlobalLayoutListener layoutListener; // for layout stuff, only used once!
+ private ViewTreeObserver.OnScrollChangedListener scrollListener;
private AsyncTask detailFetchTask;
+ private LicenseList licenseList;
@Override
@@ -76,18 +73,11 @@ public class MediaDetailFragment extends SherlockFragment {
outState.putBoolean("editable", editable);
getScrollPosition();
- outState.putInt("listIndex", initialListIndex);
outState.putInt("listTop", initialListTop);
}
private void getScrollPosition() {
- int initialListIndex = listView.getFirstVisiblePosition();
- View firstVisibleItem = listView.getChildAt(initialListIndex);
- if (firstVisibleItem == null) {
- initialListTop = 0;
- } else {
- initialListTop = firstVisibleItem.getTop();
- }
+ initialListTop = scrollView.getScrollY();
}
@Override
@@ -97,11 +87,11 @@ public class MediaDetailFragment extends SherlockFragment {
if(savedInstanceState != null) {
editable = savedInstanceState.getBoolean("editable");
index = savedInstanceState.getInt("index");
- initialListIndex = savedInstanceState.getInt("listIndex");
initialListTop = savedInstanceState.getInt("listTop");
} else {
editable = getArguments().getBoolean("editable");
index = getArguments().getInt("index");
+ initialListTop = 0;
}
final Media media = detailProvider.getMediaAtPosition(index);
categoryNames = new ArrayList();
@@ -112,29 +102,16 @@ public class MediaDetailFragment extends SherlockFragment {
image = (ImageView) view.findViewById(R.id.mediaDetailImage);
loadingProgress = (ProgressBar) view.findViewById(R.id.mediaDetailImageLoading);
loadingFailed = (ImageView) view.findViewById(R.id.mediaDetailImageFailed);
- listView = (ListView) view.findViewById(R.id.mediaDetailListView);
+ scrollView = (ScrollView) view.findViewById(R.id.mediaDetailScrollView);
// Detail consists of a list view with main pane in header view, plus category list.
- View detailView = getActivity().getLayoutInflater().inflate(R.layout.detail_main_panel, null, false);
- listView.addHeaderView(detailView, null, false);
- categoryAdapter = new ArrayAdapter(getActivity(), R.layout.detail_category_item, categoryNames);
- listView.setAdapter(categoryAdapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView> adapterView, View view, int position, long id) {
- if (categoriesLoaded && categoriesPresent) {
- String selectedCategoryTitle = "Category:" + categoryNames.get(position - 1);
- Intent viewIntent = new Intent();
- viewIntent.setAction(Intent.ACTION_VIEW);
- viewIntent.setData(Utils.uriForWikiPage(selectedCategoryTitle));
- startActivity(viewIntent);
- }
- }
- });
+ spacer = (MediaDetailSpacer) view.findViewById(R.id.mediaDetailSpacer);
+ title = (TextView) view.findViewById(R.id.mediaDetailTitle);
+ desc = (TextView) view.findViewById(R.id.mediaDetailDesc);
+ license = (TextView) view.findViewById(R.id.mediaDetailLicense);
+ categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer);
- spacer = (MediaDetailSpacer) detailView.findViewById(R.id.mediaDetailSpacer);
- title = (TextView) detailView.findViewById(R.id.mediaDetailTitle);
- desc = (TextView) detailView.findViewById(R.id.mediaDetailDesc);
- license = (TextView) detailView.findViewById(R.id.mediaDetailLicense);
+ licenseList = new LicenseList(getActivity());
// Enable or disable editing on the title
/*
@@ -162,11 +139,9 @@ public class MediaDetailFragment extends SherlockFragment {
// FIXME: cache this data
detailFetchTask = new AsyncTask() {
private MediaDataExtractor extractor;
- private LicenseList licenseList;
@Override
protected void onPreExecute() {
- licenseList = new LicenseList(getActivity());
extractor = new MediaDataExtractor(media.getFilename(), licenseList);
}
@@ -189,17 +164,8 @@ public class MediaDetailFragment extends SherlockFragment {
extractor.fill(media);
// Fill some fields
- desc.setText(media.getDescription("en"));
-
- String licenseKey = media.getLicense();
- License licenseObj = licenseList.get(licenseKey);
- if (licenseObj == null) {
- license.setText(licenseKey);
- } else {
- license.setText(licenseObj.getName());
- }
- Log.d("Commons", "Media license is: " + media.getLicense());
-
+ desc.setText(prettyDescription(media));
+ license.setText(prettyLicense(media));
categoryNames.removeAll(categoryNames);
categoryNames.addAll(media.getCategories());
@@ -210,8 +176,7 @@ public class MediaDetailFragment extends SherlockFragment {
// Stick in a filler element.
categoryNames.add(getString(R.string.detail_panel_cats_none));
}
-
- categoryAdapter.notifyDataSetChanged();
+ rebuildCatList();
} else {
Log.d("Commons", "Failed to load photo details.");
}
@@ -266,15 +231,23 @@ public class MediaDetailFragment extends SherlockFragment {
});
*/
- // Layout observer to size the spacer item relative to the available space.
+ // Progressively darken the image in the background when we scroll detail pane up
+ scrollListener = new ViewTreeObserver.OnScrollChangedListener() {
+ public void onScrollChanged() {
+ updateTheDarkness();
+ }
+ };
+ view.getViewTreeObserver().addOnScrollChangedListener(scrollListener);
+
+ // Layout layoutListener to size the spacer item relative to the available space.
// There may be a .... better way to do this.
- observer = new ViewTreeObserver.OnGlobalLayoutListener() {
+ layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
private int currentHeight = -1;
public void onGlobalLayout() {
int viewHeight = view.getHeight();
//int textHeight = title.getLineHeight();
- int paddingDp = 48;
+ int paddingDp = 112;
float paddingPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingDp, getResources().getDisplayMetrics());
int newHeight = viewHeight - Math.round(paddingPx);
@@ -284,15 +257,12 @@ public class MediaDetailFragment extends SherlockFragment {
params.height = newHeight;
spacer.setLayoutParams(params);
- // hack hack to trigger relayout
- categoryAdapter.notifyDataSetChanged();
-
- listView.setSelectionFromTop(initialListIndex, initialListTop);
+ scrollView.scrollTo(0, initialListTop);
}
}
};
- view.getViewTreeObserver().addOnGlobalLayoutListener(observer);
+ view.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
return view;
}
@@ -309,10 +279,78 @@ public class MediaDetailFragment extends SherlockFragment {
detailFetchTask.cancel(true);
detailFetchTask = null;
}
- if (observer != null) {
- getView().getViewTreeObserver().removeGlobalOnLayoutListener(observer); // old Android was on crack. CRACK IS WHACK
- observer = null;
+ if (layoutListener != null) {
+ getView().getViewTreeObserver().removeGlobalOnLayoutListener(layoutListener); // old Android was on crack. CRACK IS WHACK
+ layoutListener = null;
+ }
+ if (scrollListener != null) {
+ getView().getViewTreeObserver().removeOnScrollChangedListener(scrollListener);
+ scrollListener = null;
}
super.onDestroyView();
}
+
+ private void rebuildCatList() {
+ // @fixme add the category items
+ for (String cat : categoryNames) {
+ View catLabel = buildCatLabel(cat);
+ categoryContainer.addView(catLabel);
+ }
+ }
+
+ private View buildCatLabel(String cat) {
+ final String catName = cat;
+ final View item = getLayoutInflater(null).inflate(R.layout.detail_category_item, null, false);
+ final TextView textView = (TextView)item.findViewById(R.id.mediaDetailCategoryItemText);
+
+ textView.setText(cat);
+ if (categoriesLoaded && categoriesPresent) {
+ textView.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View view) {
+ String selectedCategoryTitle = "Category:" + catName;
+ Intent viewIntent = new Intent();
+ viewIntent.setAction(Intent.ACTION_VIEW);
+ viewIntent.setData(Utils.uriForWikiPage(selectedCategoryTitle));
+ startActivity(viewIntent);
+ }
+ });
+ }
+ return item;
+ }
+
+ private void updateTheDarkness() {
+ // You must face the darkness alone
+ int scrollY = scrollView.getScrollY();
+ int scrollMax = getView().getHeight();
+ float scrollPercentage = (float)scrollY / (float)scrollMax;
+ final float transparencyMax = 0.75f;
+ if (scrollPercentage > transparencyMax) {
+ scrollPercentage = transparencyMax;
+ }
+ image.setAlpha(1.0f - scrollPercentage);
+ }
+
+ private String prettyDescription(Media media) {
+ // @todo use UI language when multilingual descs are available
+ String desc = media.getDescription("en").trim();
+ if (desc.equals("")) {
+ return getString(R.string.detail_description_empty);
+ } else {
+ return desc;
+ }
+ }
+
+ private String prettyLicense(Media media) {
+ String licenseKey = media.getLicense();
+ Log.d("Commons", "Media license is: " + licenseKey);
+ if (licenseKey.equals("")) {
+ return getString(R.string.detail_license_empty);
+ }
+ License licenseObj = licenseList.get(licenseKey);
+ if (licenseObj == null) {
+ return licenseKey;
+ } else {
+ return licenseObj.getName();
+ }
+ }
}