diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6d927ae32..08c034216 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -404,6 +404,17 @@
android:value=".FDroid" />
+
+
+
{
+
+ private final int VIEWTYPE_HEADER = 0;
+ private final int VIEWTYPE_SCREENSHOTS = 1;
+ private final int VIEWTYPE_WHATS_NEW = 2;
+
+ private final Context mContext;
+ private ArrayList mItems;
+
+ public AppDetailsRecyclerViewAdapter(Context context) {
+ mContext = context;
+ updateItems();
+ }
+
+ private void updateItems() {
+ if (mItems == null)
+ mItems = new ArrayList<>();
+ else
+ mItems.clear();
+ mItems.add(Integer.valueOf(VIEWTYPE_HEADER));
+ mItems.add(Integer.valueOf(VIEWTYPE_SCREENSHOTS));
+ mItems.add(Integer.valueOf(VIEWTYPE_WHATS_NEW));
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType == VIEWTYPE_HEADER) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.app_details2_header, parent, false);
+ return new HeaderViewHolder(view);
+ } else if (viewType == VIEWTYPE_SCREENSHOTS) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.app_details2_screenshots, parent, false);
+ return new ScreenShotsViewHolder(view);
+ } else if (viewType == VIEWTYPE_WHATS_NEW) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.app_details2_whatsnew, parent, false);
+ return new WhatsNewViewHolder(view);
+ }
+ return null;
+ }
+
+ @Override
+ public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
+ int viewType = mItems.get(position);
+ if (viewType == VIEWTYPE_HEADER) {
+ final HeaderViewHolder vh = (HeaderViewHolder) holder;
+ ImageLoader.getInstance().displayImage(mApp.iconUrlLarge, vh.iconView, vh.displayImageOptions);
+ vh.titleView.setText(mApp.name);
+ if (!TextUtils.isEmpty(mApp.author)) {
+ vh.authorView.setText(getString(R.string.by_author) + " " + mApp.author);
+ vh.authorView.setVisibility(View.VISIBLE);
+ } else {
+ vh.authorView.setVisibility(View.GONE);
+ }
+ vh.summaryView.setText(mApp.summary);
+ final Spanned desc = Html.fromHtml(mApp.description, null, new Utils.HtmlTagHandler());
+ vh.descriptionView.setMovementMethod(AppDetails2.SafeLinkMovementMethod.getInstance(mContext));
+ vh.descriptionView.setText(trimNewlines(desc));
+ vh.descriptionView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (vh.descriptionView.getLineCount() < HeaderViewHolder.MAX_LINES) {
+ vh.descriptionMoreView.setVisibility(View.GONE);
+ } else {
+ vh.descriptionMoreView.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ vh.buttonSecondaryView.setText(R.string.menu_uninstall);
+ vh.buttonSecondaryView.setVisibility(mApp.isInstalled() ? View.VISIBLE : View.INVISIBLE);
+ vh.buttonPrimaryView.setText(R.string.menu_install);
+ vh.buttonPrimaryView.setVisibility(View.VISIBLE);
+
+/* if (appDetails.activeDownloadUrlString != null) {
+ btMain.setText(R.string.downloading);
+ btMain.setEnabled(false);
+ } else if (!app.isInstalled() && app.suggestedVersionCode > 0 &&
+ appDetails.adapter.getCount() > 0) {
+ // Check count > 0 due to incompatible apps resulting in an empty list.
+ // If App isn't installed
+ installed = false;
+ statusView.setText(R.string.details_notinstalled);
+ NfcHelper.disableAndroidBeam(appDetails);
+ // Set Install button and hide second button
+ btMain.setText(R.string.menu_install);
+ btMain.setOnClickListener(mOnClickListener);
+ btMain.setEnabled(true);
+ } else if (app.isInstalled()) {
+ // If App is installed
+ installed = true;
+ statusView.setText(getString(R.string.details_installed, app.installedVersionName));
+ NfcHelper.setAndroidBeam(appDetails, app.packageName);
+ if (app.canAndWantToUpdate(appDetails)) {
+ updateWanted = true;
+ btMain.setText(R.string.menu_upgrade);
+ } else {
+ updateWanted = false;
+ if (appDetails.packageManager.getLaunchIntentForPackage(app.packageName) != null) {
+ btMain.setText(R.string.menu_launch);
+ } else {
+ btMain.setText(R.string.menu_uninstall);
+ }
+ }
+ btMain.setOnClickListener(mOnClickListener);
+ btMain.setEnabled(true);
+ }
+
+ TextView currentVersion = (TextView) view.findViewById(R.id.current_version);
+ if (!appDetails.getApks().isEmpty()) {
+ currentVersion.setText(appDetails.getApks().getItem(0).versionName + " (" + app.license + ")");
+ } else {
+ currentVersion.setVisibility(View.GONE);
+ btMain.setVisibility(View.GONE);
+ }*/
+
+ } else if (viewType == VIEWTYPE_SCREENSHOTS) {
+ ScreenShotsViewHolder vh = (ScreenShotsViewHolder) holder;
+ LinearLayoutManager lm = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
+ vh.recyclerView.setLayoutManager(lm);
+ ScreenShotsRecyclerViewAdapter adapter = new ScreenShotsRecyclerViewAdapter(mApp);
+ vh.recyclerView.setAdapter(adapter);
+ vh.recyclerView.setHasFixedSize(true);
+ vh.recyclerView.setNestedScrollingEnabled(false);
+ LinearLayoutManagerSnapHelper helper = new LinearLayoutManagerSnapHelper(lm);
+ helper.setLinearSnapHelperListener(adapter);
+ helper.attachToRecyclerView(vh.recyclerView);
+ } else if (viewType == VIEWTYPE_WHATS_NEW) {
+ WhatsNewViewHolder vh = (WhatsNewViewHolder) holder;
+ vh.textView.setText("WHATS NEW GOES HERE");
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItems.size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mItems.get(position);
+ }
+
+ public class HeaderViewHolder extends RecyclerView.ViewHolder {
+ private static final int MAX_LINES = 5;
+
+ final ImageView iconView;
+ final TextView titleView;
+ final TextView authorView;
+ final TextView summaryView;
+ final TextView descriptionView;
+ final TextView descriptionMoreView;
+ final Button buttonPrimaryView;
+ final Button buttonSecondaryView;
+ final DisplayImageOptions displayImageOptions;
+
+ HeaderViewHolder(View view) {
+ super(view);
+ iconView = (ImageView) view.findViewById(R.id.icon);
+ titleView = (TextView) view.findViewById(R.id.title);
+ authorView = (TextView) view.findViewById(R.id.author);
+ summaryView = (TextView) view.findViewById(R.id.summary);
+ descriptionView = (TextView) view.findViewById(R.id.description);
+ descriptionMoreView = (TextView) view.findViewById(R.id.description_more);
+ buttonPrimaryView = (Button) view.findViewById(R.id.primaryButtonView);
+ buttonSecondaryView = (Button) view.findViewById(R.id.secondaryButtonView);
+ displayImageOptions = new DisplayImageOptions.Builder()
+ .cacheInMemory(true)
+ .cacheOnDisk(true)
+ .imageScaleType(ImageScaleType.NONE)
+ .showImageOnLoading(R.drawable.ic_repo_app_default)
+ .showImageForEmptyUri(R.drawable.ic_repo_app_default)
+ .bitmapConfig(Bitmap.Config.RGB_565)
+ .build();
+ descriptionView.setMaxLines(MAX_LINES);
+ descriptionView.setEllipsize(TextUtils.TruncateAt.MARQUEE);
+ descriptionMoreView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Remember current scroll position so that we can restore it
+ LinearLayoutManager lm = (LinearLayoutManager)mRecyclerView.getLayoutManager();
+ int pos = lm.findFirstVisibleItemPosition();
+ int posOffset = 0;
+ if (pos != NO_POSITION) {
+ View view = lm.findViewByPosition(pos);
+ if (view != null)
+ posOffset = lm.getDecoratedTop(view);
+ }
+ if (TextViewCompat.getMaxLines(descriptionView) != MAX_LINES) {
+ descriptionView.setMaxLines(MAX_LINES);
+ descriptionMoreView.setText(R.string.more);
+ } else {
+ descriptionView.setMaxLines(Integer.MAX_VALUE);
+ descriptionMoreView.setText(R.string.less);
+ }
+ if (pos != NO_POSITION) {
+ // Restore scroll position
+ lm.scrollToPositionWithOffset(pos, posOffset);
+ }
+ }
+ });
+ // Set ALL caps (in a way compatible with SDK 10)
+ AllCapsTransformationMethod allCapsTransformation = new AllCapsTransformationMethod(view.getContext());
+ buttonPrimaryView.setTransformationMethod(allCapsTransformation);
+ buttonSecondaryView.setTransformationMethod(allCapsTransformation);
+ descriptionMoreView.setTransformationMethod(allCapsTransformation);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " '" + titleView.getText() + "'";
+ }
+ }
+
+ public class ScreenShotsViewHolder extends RecyclerView.ViewHolder {
+ final RecyclerView recyclerView;
+
+ ScreenShotsViewHolder(View view) {
+ super(view);
+ recyclerView = (RecyclerView) view.findViewById(R.id.screenshots);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " screenshots";
+ }
+ }
+
+ public class WhatsNewViewHolder extends RecyclerView.ViewHolder {
+ final TextView textView;
+
+ WhatsNewViewHolder(View view) {
+ super(view);
+ textView = (TextView) view.findViewById(R.id.text);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " " + textView.getText();
+ }
+ }
+
+ class ScreenShotsRecyclerViewAdapter extends RecyclerView.Adapter implements LinearLayoutManagerSnapHelper.LinearSnapHelperListener {
+ private final App app;
+ private final DisplayImageOptions displayImageOptions;
+ private View selectedView;
+ private int selectedPosition;
+ private int selectedItemElevation;
+ private int unselectedItemMargin;
+
+ public ScreenShotsRecyclerViewAdapter(App app) {
+ super();
+ this.app = app;
+ selectedPosition = 0;
+ selectedItemElevation = getResources().getDimensionPixelSize(R.dimen.details_screenshot_selected_elevation);
+ unselectedItemMargin = getResources().getDimensionPixelSize(R.dimen.details_screenshot_margin);
+ displayImageOptions = new DisplayImageOptions.Builder()
+ .cacheInMemory(true)
+ .cacheOnDisk(true)
+ .imageScaleType(ImageScaleType.NONE)
+ .showImageOnLoading(R.drawable.ic_repo_app_default)
+ .showImageForEmptyUri(R.drawable.ic_repo_app_default)
+ .bitmapConfig(Bitmap.Config.RGB_565)
+ .build();
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ ScreenShotViewHolder vh = (ScreenShotViewHolder) holder;
+ setViewSelected(vh.itemView, position == selectedPosition);
+ if (position == selectedPosition)
+ this.selectedView = vh.itemView;
+ ImageLoader.getInstance().displayImage(mApp.iconUrlLarge, vh.image, displayImageOptions);
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.app_details2_screenshot_item, parent, false);
+ return new ScreenShotViewHolder(view);
+ }
+
+ @Override
+ public int getItemCount() {
+ return 7;
+ }
+
+ @Override
+ public void onSnappedToView(View view, int snappedPosition) {
+ setViewSelected(selectedView, false);
+ selectedView = view;
+ selectedPosition = snappedPosition;
+ setViewSelected(selectedView, true);
+ }
+
+ private void setViewSelected(View view, boolean selected) {
+ if (view != null) {
+ RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams)view.getLayoutParams();
+ if (selected)
+ lp.setMargins(0,selectedItemElevation,0,selectedItemElevation);
+ else
+ lp.setMargins(0,unselectedItemMargin,0,unselectedItemMargin);
+ ViewCompat.setElevation(view, selected ? selectedItemElevation : 0);
+ view.setLayoutParams(lp);
+ }
+ }
+
+ public class ScreenShotViewHolder extends RecyclerView.ViewHolder {
+ final ImageView image;
+
+ ScreenShotViewHolder(View view) {
+ super(view);
+ image = (ImageView) view.findViewById(R.id.image);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " screenshot";
+ }
+ }
+ }
+ }
+
+ // The HTML formatter adds "\n\n" at the end of every paragraph. This
+ // is desired between paragraphs, but not at the end of the whole
+ // string as it adds unwanted spacing at the end of the TextView.
+ // Remove all trailing newlines.
+ // Use this function instead of a trim() as that would require
+ // converting to String and thus losing formatting (e.g. bold).
+ private static CharSequence trimNewlines(CharSequence s) {
+ if (s == null || s.length() < 1) {
+ return s;
+ }
+ int i;
+ for (i = s.length() - 1; i >= 0; i--) {
+ if (s.charAt(i) != '\n') {
+ break;
+ }
+ }
+ if (i == s.length() - 1) {
+ return s;
+ }
+ return s.subSequence(0, i + 1);
+ }
+
+ private static final class SafeLinkMovementMethod extends LinkMovementMethod {
+
+ private static AppDetails2.SafeLinkMovementMethod instance;
+
+ private final Context ctx;
+
+ private SafeLinkMovementMethod(Context ctx) {
+ this.ctx = ctx;
+ }
+
+ public static AppDetails2.SafeLinkMovementMethod getInstance(Context ctx) {
+ if (instance == null) {
+ instance = new AppDetails2.SafeLinkMovementMethod(ctx);
+ }
+ return instance;
+ }
+
+ private static CharSequence getLink(TextView widget, Spannable buffer,
+ MotionEvent event) {
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+ x -= widget.getTotalPaddingLeft();
+ y -= widget.getTotalPaddingTop();
+ x += widget.getScrollX();
+ y += widget.getScrollY();
+
+ Layout layout = widget.getLayout();
+ final int line = layout.getLineForVertical(y);
+ final int off = layout.getOffsetForHorizontal(line, x);
+ final ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
+
+ if (links.length > 0) {
+ final ClickableSpan link = links[0];
+ final Spanned s = (Spanned) widget.getText();
+ return s.subSequence(s.getSpanStart(link), s.getSpanEnd(link));
+ }
+ return "null";
+ }
+
+ @Override
+ public boolean onTouchEvent(@NonNull TextView widget, @NonNull Spannable buffer,
+ @NonNull MotionEvent event) {
+ try {
+ return super.onTouchEvent(widget, buffer, event);
+ } catch (ActivityNotFoundException ex) {
+ Selection.removeSelection(buffer);
+ final CharSequence link = getLink(widget, buffer, event);
+ Toast.makeText(ctx,
+ ctx.getString(R.string.no_handler_app, link),
+ Toast.LENGTH_LONG).show();
+ return true;
+ }
+ }
+
+ }
+}
diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java
index eca09c6bd..fec4b0e6d 100644
--- a/app/src/main/java/org/fdroid/fdroid/Utils.java
+++ b/app/src/main/java/org/fdroid/fdroid/Utils.java
@@ -20,6 +20,7 @@ package org.fdroid.fdroid;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -31,6 +32,7 @@ import android.text.Html;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.TypedValue;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
@@ -596,4 +598,9 @@ public final class Utils {
return data;
}
+ public static int dpToPx(int dp, Context ctx)
+ {
+ Resources r = ctx.getResources();
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
+ }
}
diff --git a/app/src/main/java/org/fdroid/fdroid/views/LinearLayoutManagerSnapHelper.java b/app/src/main/java/org/fdroid/fdroid/views/LinearLayoutManagerSnapHelper.java
new file mode 100644
index 000000000..ebbecf2eb
--- /dev/null
+++ b/app/src/main/java/org/fdroid/fdroid/views/LinearLayoutManagerSnapHelper.java
@@ -0,0 +1,74 @@
+package org.fdroid.fdroid.views;
+
+import android.support.v4.view.ViewCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.LinearSnapHelper;
+import android.support.v7.widget.OrientationHelper;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import static android.support.v7.widget.RecyclerView.NO_POSITION;
+
+public class LinearLayoutManagerSnapHelper extends LinearSnapHelper {
+
+ public interface LinearSnapHelperListener {
+ /**
+ * Tells the listener that we have selected a view to snap to.
+ * @param view The selected view (may be null)
+ * @param position Adapter position of the snapped to view (or NO_POSITION if none)
+ */
+ void onSnappedToView(View view, int position);
+ };
+
+ private LinearLayoutManager mLlm;
+ private OrientationHelper mOrientationHelper;
+ private LinearSnapHelperListener mListener;
+
+ public LinearLayoutManagerSnapHelper(LinearLayoutManager llm) {
+ this.mLlm = llm;
+ this.mOrientationHelper = OrientationHelper.createHorizontalHelper(mLlm);
+ };
+
+ public void setLinearSnapHelperListener(LinearSnapHelperListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public View findSnapView(RecyclerView.LayoutManager layoutManager) {
+ View snappedView = super.findSnapView(layoutManager);
+ if (layoutManager.canScrollHorizontally()) {
+ if (layoutManager instanceof LinearLayoutManager) {
+ int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
+ int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
+ if (firstChild == 0) {
+ View child = layoutManager.findViewByPosition(firstChild);
+ if (mOrientationHelper.getDecoratedEnd(child) >= mOrientationHelper.getDecoratedMeasurement(child) / 2
+ && mOrientationHelper.getDecoratedEnd(child) > 0) {
+ int dist1 = super.calculateDistanceToFinalSnap(layoutManager, snappedView)[0];
+ int dist2 = mOrientationHelper.getDecoratedStart(child);
+ if (Math.abs(dist1) > Math.abs(dist2)) {
+ snappedView = child;
+ }
+ }
+ } else if (lastChild == (mLlm.getItemCount() - 1)) {
+ View child = layoutManager.findViewByPosition(lastChild);
+ if (mOrientationHelper.getDecoratedStart(child) < mOrientationHelper.getTotalSpace() - mOrientationHelper.getDecoratedMeasurement(child) / 2
+ && mOrientationHelper.getDecoratedStart(child) < mOrientationHelper.getTotalSpace()) {
+ int dist1 = super.calculateDistanceToFinalSnap(layoutManager, snappedView)[0];
+ int dist2 = mOrientationHelper.getTotalSpace() - mOrientationHelper.getDecoratedEnd(child);
+ if (Math.abs(dist1) > Math.abs(dist2)) {
+ snappedView = child;
+ }
+ }
+ }
+ }
+ }
+ if (mListener != null) {
+ int snappedPosition = 0;
+ if (snappedView != null)
+ snappedPosition = mLlm.getPosition(snappedView);
+ mListener.onSnappedToView(snappedView, snappedPosition);
+ }
+ return snappedView;
+ }
+}
diff --git a/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java b/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java
index 188861f01..702b2470d 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/fragments/AppListFragment.java
@@ -20,6 +20,7 @@ import android.widget.AdapterView;
import android.widget.TextView;
import org.fdroid.fdroid.AppDetails;
+import org.fdroid.fdroid.AppDetails2;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.UpdateService;
@@ -30,6 +31,7 @@ import org.fdroid.fdroid.views.AppListAdapter;
public abstract class AppListFragment extends ListFragment implements
AdapterView.OnItemClickListener,
+ AdapterView.OnItemLongClickListener,
Preferences.ChangeListener,
LoaderManager.LoaderCallbacks {
@@ -109,6 +111,7 @@ public abstract class AppListFragment extends ListFragment implements
// returns the list view is "called between onCreate and
// onActivityCreated" according to the docs.
getListView().setOnItemClickListener(this);
+ getListView().setOnItemLongClickListener(this);
}
@Override
@@ -155,11 +158,21 @@ public abstract class AppListFragment extends ListFragment implements
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ showItemDetails(view, position, false);
+ }
+
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ showItemDetails(view, position, true);
+ return true;
+ }
+
+ private void showItemDetails(View view, int position, boolean useNewDetailsActivity) {
// Cursor is null in the swap list when touching the first item.
Cursor cursor = (Cursor) getListView().getItemAtPosition(position);
if (cursor != null) {
final App app = new App(cursor);
- Intent intent = getAppDetailsIntent();
+ Intent intent = getAppDetailsIntent(useNewDetailsActivity);
intent.putExtra(AppDetails.EXTRA_APPID, app.packageName);
intent.putExtra(AppDetails.EXTRA_FROM, getFromTitle());
if (Build.VERSION.SDK_INT >= 21) {
@@ -176,8 +189,8 @@ public abstract class AppListFragment extends ListFragment implements
}
}
- private Intent getAppDetailsIntent() {
- return new Intent(getActivity(), AppDetails.class);
+ private Intent getAppDetailsIntent(boolean useNewDetailsActivity) {
+ return new Intent(getActivity(), useNewDetailsActivity ? AppDetails2.class : AppDetails.class);
}
@Override
diff --git a/app/src/main/res/drawable-mdpi/feature_placeholder.png b/app/src/main/res/drawable-mdpi/feature_placeholder.png
new file mode 100644
index 000000000..861559285
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/feature_placeholder.png differ
diff --git a/app/src/main/res/drawable/button_primary_background_selector.xml b/app/src/main/res/drawable/button_primary_background_selector.xml
new file mode 100644
index 000000000..ee21a1543
--- /dev/null
+++ b/app/src/main/res/drawable/button_primary_background_selector.xml
@@ -0,0 +1,27 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/button_secondary_background_selector.xml b/app/src/main/res/drawable/button_secondary_background_selector.xml
new file mode 100644
index 000000000..2cb0d8ebb
--- /dev/null
+++ b/app/src/main/res/drawable/button_secondary_background_selector.xml
@@ -0,0 +1,28 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_app_details2.xml b/app/src/main/res/layout/activity_app_details2.xml
new file mode 100644
index 000000000..d71539052
--- /dev/null
+++ b/app/src/main/res/layout/activity_app_details2.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/app_details2_header.xml b/app/src/main/res/layout/app_details2_header.xml
new file mode 100755
index 000000000..8a2217e4a
--- /dev/null
+++ b/app/src/main/res/layout/app_details2_header.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/app_details2_screenshot_item.xml b/app/src/main/res/layout/app_details2_screenshot_item.xml
new file mode 100644
index 000000000..02f2b6057
--- /dev/null
+++ b/app/src/main/res/layout/app_details2_screenshot_item.xml
@@ -0,0 +1,19 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/app_details2_screenshots.xml b/app/src/main/res/layout/app_details2_screenshots.xml
new file mode 100644
index 000000000..94eb2f708
--- /dev/null
+++ b/app/src/main/res/layout/app_details2_screenshots.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/app_details2_whatsnew.xml b/app/src/main/res/layout/app_details2_whatsnew.xml
new file mode 100755
index 000000000..6bd8d9c1e
--- /dev/null
+++ b/app/src/main/res/layout/app_details2_whatsnew.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/content_app_details2.xml b/app/src/main/res/layout/content_app_details2.xml
new file mode 100644
index 000000000..2fe6266c5
--- /dev/null
+++ b/app/src/main/res/layout/content_app_details2.xml
@@ -0,0 +1,14 @@
+
+
+
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
index 454cb114a..accd2a43e 100644
--- a/app/src/main/res/values-v21/styles.xml
+++ b/app/src/main/res/values-v21/styles.xml
@@ -18,4 +18,11 @@
- #04b9e6
+
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index e57eb563d..d083a7db0 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -3,5 +3,10 @@
16dp
48dp
+ 180dp
+
+ 16dp
+
+ 3dp
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index b6ff997b4..e1c5e5a92 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -246,4 +246,13 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/values/styles_detail.xml b/app/src/main/res/values/styles_detail.xml
new file mode 100644
index 000000000..fb4290e8c
--- /dev/null
+++ b/app/src/main/res/values/styles_detail.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file