Refresh layout of AppDetails screen

This change primarily affects the AppDetails links section to make them easier to click. It also strips down the UI a bit to provide a cleaner interface as well as some modest Material Design tweaks.

Fixes #389.
This commit is contained in:
Jeff Mixon 2015-10-05 14:32:10 +02:00
parent a0ad3ee07d
commit 36e0479967
11 changed files with 298 additions and 296 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -22,8 +22,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="8dp" android:paddingBottom="8dp"
android:paddingLeft="5dp" android:paddingLeft="@dimen/layout_horizontal_margin"
android:paddingRight="5dp" android:paddingStart="@dimen/layout_horizontal_margin"
android:paddingRight="@dimen/layout_horizontal_margin"
android:paddingEnd="@dimen/layout_horizontal_margin"
android:paddingTop="4dp"> android:paddingTop="4dp">
<TextView <TextView
@ -91,142 +93,111 @@ Android is open in the sense that you are free to install apks from anywhere you
Changelog" /> Changelog" />
<ImageView <TextView
android:id="@+id/view_more_description" android:id="@+id/view_more_description"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|center_horizontal"
android:contentDescription="@string/content_description_view_more" android:text="@string/more"
android:src="@drawable/ic_expand_more_grey600" android:textAllCaps="true"
tools:src="@drawable/ic_expand_more_grey600" /> android:textSize="14sp"
android:layout_marginTop="8dp"
android:textColor="?android:textColorSecondary"
tools:ignore="UnusedAttribute" />
</LinearLayout> </LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="2px"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/listDivider"
tools:ignore="PxUsage" />
<LinearLayout <LinearLayout
android:id="@+id/ll_information" android:id="@+id/ll_information"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:orientation="vertical"> android:orientation="vertical"
tools:ignore="UnusedAttribute">
<TextView <TextView
android:id="@+id/information" android:id="@+id/information"
android:layout_width="wrap_content" style="@style/AppDetailsSubheaderText"
android:layout_height="wrap_content"
android:layout_marginTop="8sp"
android:drawableRight="@drawable/ic_expand_more_grey600"
android:drawablePadding="4dp"
android:drawableEnd="@drawable/ic_expand_more_grey600"
android:singleLine="true"
android:text="@string/links" android:text="@string/links"
android:textStyle="bold" android:drawableRight="@drawable/ic_expand_more_grey600"
tools:text="@string/links" android:drawableEnd="@drawable/ic_expand_more_grey600"
tools:drawableRight="@drawable/ic_expand_more_grey600"/> android:drawableLeft="@drawable/ic_website"
android:drawableStart="@drawable/ic_website" />
<LinearLayout <LinearLayout
android:id="@+id/ll_information_content" android:id="@+id/ll_information_content"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" android:orientation="vertical"
android:orientation="vertical"> android:layout_marginLeft="@dimen/layout_horizontal_margin"
android:layout_marginStart="@dimen/layout_horizontal_margin"
android:visibility="gone">
<TextView <TextView
android:id="@+id/source" android:id="@+id/source"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_source_code" android:drawableLeft="@drawable/ic_source_code"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_source_code" android:drawableStart="@drawable/ic_source_code"
android:gravity="center_vertical" android:text="@string/menu_source" />
android:text="@string/menu_source"
tools:text="@string/menu_source" />
<TextView <TextView
android:id="@+id/issues" android:id="@+id/issues"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_issues" android:drawableLeft="@drawable/ic_issues"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_issues" android:drawableStart="@drawable/ic_issues"
android:gravity="center_vertical" android:text="@string/menu_issues" />
android:paddingTop="4dp"
android:text="@string/menu_issues"
tools:text="@string/menu_issues" />
<TextView <TextView
android:id="@+id/changelog" android:id="@+id/changelog"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_changelog" android:drawableLeft="@drawable/ic_changelog"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_changelog" android:drawableStart="@drawable/ic_changelog"
android:gravity="center_vertical" android:text="@string/menu_changelog" />
android:paddingTop="4dp"
android:text="@string/menu_changelog"
tools:text="@string/menu_changelog" />
<TextView <TextView
android:id="@+id/website" android:id="@+id/website"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_website" android:drawableLeft="@drawable/ic_website"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_website" android:drawableStart="@drawable/ic_website"
android:gravity="center_vertical" android:text="@string/menu_website" />
android:paddingTop="4dp"
android:text="@string/menu_website"
tools:text="@string/menu_website" />
<TextView <TextView
android:id="@+id/donate" android:id="@+id/donate"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_donate" android:drawableLeft="@drawable/ic_donate"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_donate" android:drawableStart="@drawable/ic_donate"
android:gravity="center_vertical" android:text="@string/menu_donate" />
android:paddingTop="4dp"
android:text="@string/menu_donate"
tools:text="@string/menu_donate" />
<TextView <TextView
android:id="@+id/bitcoin" android:id="@+id/bitcoin"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_bitcoin" android:drawableLeft="@drawable/ic_bitcoin"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_bitcoin" android:drawableStart="@drawable/ic_bitcoin"
android:gravity="center_vertical" android:text="@string/menu_bitcoin" />
android:paddingTop="4dp"
android:text="@string/menu_bitcoin"
tools:text="@string/menu_bitcoin" />
<TextView <TextView
android:id="@+id/litecoin" android:id="@+id/litecoin"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_litecoin" android:drawableLeft="@drawable/ic_litecoin"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_litecoin" android:drawableStart="@drawable/ic_litecoin"
android:gravity="center_vertical" android:text="@string/menu_litecoin" />
android:paddingTop="4dp"
android:text="@string/menu_litecoin"
tools:text="@string/menu_litecoin" />
<TextView <TextView
android:id="@+id/flattr" android:id="@+id/flattr"
android:layout_width="wrap_content" style="@style/AppDetailsLink"
android:layout_height="match_parent"
android:drawableLeft="@drawable/ic_flattr" android:drawableLeft="@drawable/ic_flattr"
android:drawablePadding="4dp"
android:drawableStart="@drawable/ic_flattr" android:drawableStart="@drawable/ic_flattr"
android:gravity="center_vertical" android:text="@string/menu_flattr" />
android:paddingTop="4dp"
android:text="@string/menu_flattr"
tools:text="@string/menu_flattr" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -234,27 +205,29 @@ Changelog" />
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:orientation="vertical"> android:orientation="vertical"
android:layout_marginBottom="8dp"
tools:ignore="UnusedAttribute">
<TextView <TextView
android:id="@+id/permissions" android:id="@+id/permissions"
android:layout_width="wrap_content" style="@style/AppDetailsSubheaderText"
android:layout_height="wrap_content" android:text="@string/permissions"
android:layout_marginTop="8sp" android:drawableLeft="@drawable/ic_lock_24dp_grey600"
android:drawablePadding="4dp" android:drawableStart="@drawable/ic_lock_24dp_grey600"
android:drawableEnd="@drawable/ic_expand_more_grey600"
android:drawableRight="@drawable/ic_expand_more_grey600" android:drawableRight="@drawable/ic_expand_more_grey600"
android:singleLine="true" android:drawableEnd="@drawable/ic_expand_more_grey600" />
android:textStyle="bold"
tools:text="Permissions for version 1.0"
tools:drawableRight="@drawable/ic_expand_more_grey600"/>
<TextView <TextView
android:id="@+id/permissions_list" android:id="@+id/permissions_list"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:singleLine="false" android:singleLine="false"
android:textSize="13sp" android:fontFamily="sans-serif-light"
android:textSize="14sp"
android:visibility="gone"
android:layout_marginLeft="@dimen/layout_horizontal_margin"
android:layout_marginStart="@dimen/layout_horizontal_margin"
tools:text=" * Full network access tools:text=" * Full network access
* View network connections * View network connections
* View Wi-Fi connections * View Wi-Fi connections

View File

@ -15,4 +15,8 @@
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item> <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
</style> </style>
<style name="AppDetailsLink" parent="AppDetailsLinkBase">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
</resources> </resources>

View File

@ -4,4 +4,6 @@
<dimen name="applist_icon_normal_size">48dp</dimen> <dimen name="applist_icon_normal_size">48dp</dimen>
<dimen name="applist_icon_compact_size">32dp</dimen> <dimen name="applist_icon_compact_size">32dp</dimen>
<dimen name="layout_horizontal_margin">16dp</dimen>
<dimen name="material_listitem_height">48dp</dimen>
</resources> </resources>

View File

@ -64,6 +64,8 @@
<string name="repo_add_add">Add</string> <string name="repo_add_add">Add</string>
<string name="links">Links</string> <string name="links">Links</string>
<string name="content_description_view_more">View more</string> <string name="content_description_view_more">View more</string>
<string name="more">More</string>
<string name="less">Less</string>
<string name="back">Back</string> <string name="back">Back</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
@ -189,6 +191,7 @@
<string name="global_error_updating_repos">Error during update: %s</string> <string name="global_error_updating_repos">Error during update: %s</string>
<string name="no_permissions">No permissions are used.</string> <string name="no_permissions">No permissions are used.</string>
<string name="permissions_for_long">Permissions for version %s</string> <string name="permissions_for_long">Permissions for version %s</string>
<string name="permissions">Permissions</string>
<string name="no_handler_app">You don\'t have any available app that can handle %s.</string> <string name="no_handler_app">You don\'t have any available app that can handle %s.</string>
<string name="compactlayout">Compact Layout</string> <string name="compactlayout">Compact Layout</string>
<string name="compactlayout_on">Show icons at a smaller size</string> <string name="compactlayout_on">Show icons at a smaller size</string>

View File

@ -178,4 +178,24 @@
<item name="android:textStyle">italic</item> <item name="android:textStyle">italic</item>
</style> </style>
<style name="AppDetailsLinkBase">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/material_listitem_height</item>
<item name="android:drawablePadding">12dp</item>
<item name="android:gravity">center_vertical</item>
</style>
<style name="AppDetailsLink" parent="AppDetailsLinkBase" />
<style name="AppDetailsSubheaderTextBase">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/material_listitem_height</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:textColorPrimary</item>
<item name="android:singleLine">true</item>
<item name="android:gravity">center_vertical</item>
<item name="android:drawablePadding">12dp</item>
</style>
<style name="AppDetailsSubheaderText" parent="AppDetailsSubheaderTextBase" />
</resources> </resources>

View File

@ -43,6 +43,7 @@ import android.support.annotation.Nullable;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment; import android.support.v4.app.ListFragment;
import android.support.v4.app.NavUtils; import android.support.v4.app.NavUtils;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -1056,11 +1057,24 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
private AppDetailsData data; private AppDetailsData data;
private static final int MAX_LINES = 5; private static final int MAX_LINES = 5;
private static boolean view_all_description; private static boolean view_all_description;
private static boolean view_all_information;
private static boolean view_all_permissions;
private static LinearLayout ll_view_more_description; private static LinearLayout ll_view_more_description;
private static LinearLayout ll_view_more_information;
private static LinearLayout ll_view_more_permissions; private static LinearLayout ll_view_more_permissions;
private final View.OnClickListener expander_permissions = new View.OnClickListener() {
@Override
public void onClick(View v) {
final TextView permissionListView = (TextView) ll_view_more_permissions.findViewById(R.id.permissions_list);
final TextView permissionHeader = (TextView) ll_view_more_permissions.findViewById(R.id.permissions);
if (permissionListView.getVisibility() == View.GONE) {
permissionListView.setVisibility(View.VISIBLE);
permissionHeader.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(getActivity(), R.drawable.ic_lock_24dp_grey600), null, ContextCompat.getDrawable(getActivity(), R.drawable.ic_expand_less_grey600), null);
} else {
permissionListView.setVisibility(View.GONE);
permissionHeader.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(getActivity(), R.drawable.ic_lock_24dp_grey600), null, ContextCompat.getDrawable(getActivity(), R.drawable.ic_expand_more_grey600), null);
}
}
};
private ViewGroup layout_links;
public AppDetailsSummaryFragment() { public AppDetailsSummaryFragment() {
prefs = Preferences.get(); prefs = Preferences.get();
@ -1116,168 +1130,22 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
return s.subSequence(0, i); return s.subSequence(0, i);
} }
private void setupView(final View view) { private ViewGroup layout_links_content;
// Expandable description private View.OnClickListener expander_links = new View.OnClickListener() {
final TextView description = (TextView) view.findViewById(R.id.description); @Override
final Spanned desc = Html.fromHtml(getApp().description, null, new Utils.HtmlTagHandler()); public void onClick(View v) {
description.setMovementMethod(SafeLinkMovementMethod.getInstance(getActivity()));
description.setText(trimNewlines(desc));
final ImageView view_more_description = (ImageView) view.findViewById(R.id.view_more_description);
description.post(new Runnable() {
@Override
public void run() {
// If description has more than five lines
if (description.getLineCount() > MAX_LINES) {
description.setMaxLines(MAX_LINES);
description.setOnClickListener(expander_description);
view_all_description = true;
ll_view_more_description = (LinearLayout) view.findViewById(R.id.ll_description); TextView linksHeader = (TextView) layout_links.findViewById(R.id.information);
ll_view_more_description.setOnClickListener(expander_description);
view_more_description.setImageResource(R.drawable.ic_expand_more_grey600); if (layout_links_content.getVisibility() == View.GONE) {
view_more_description.setOnClickListener(expander_description); layout_links_content.setVisibility(View.VISIBLE);
} else { linksHeader.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(getActivity(), R.drawable.ic_website), null, ContextCompat.getDrawable(getActivity(), R.drawable.ic_expand_less_grey600), null);
view_more_description.setVisibility(View.GONE);
}
}
});
// App ID
final TextView appIdView = (TextView) view.findViewById(R.id.appid);
if (prefs.expertMode())
appIdView.setText(getApp().id);
else
appIdView.setVisibility(View.GONE);
// Expandable information
ll_view_more_information = (LinearLayout) view.findViewById(R.id.ll_information);
final TextView information = (TextView) view.findViewById(R.id.information);
final LinearLayout ll_view_more_information_content = (LinearLayout) view.findViewById(R.id.ll_information_content);
ll_view_more_information_content.setVisibility(View.GONE);
view_all_information = true;
information.setCompoundDrawablesWithIntrinsicBounds(null, null, getActivity().getResources().getDrawable(R.drawable.ic_expand_more_grey600), null);
ll_view_more_information.setOnClickListener(expander_information);
information.setOnClickListener(expander_information);
// Summary
final TextView summaryView = (TextView) view.findViewById(R.id.summary);
summaryView.setText(getApp().summary);
// Website button
TextView tv = (TextView) view.findViewById(R.id.website);
if (!TextUtils.isEmpty(getApp().webURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Source button
tv = (TextView) view.findViewById(R.id.source);
if (!TextUtils.isEmpty(getApp().sourceURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Issues button
tv = (TextView) view.findViewById(R.id.issues);
if (!TextUtils.isEmpty(getApp().trackerURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Changelog button
tv = (TextView) view.findViewById(R.id.changelog);
if (!TextUtils.isEmpty(getApp().changelogURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Donate button
tv = (TextView) view.findViewById(R.id.donate);
if (!TextUtils.isEmpty(getApp().donateURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Bitcoin
tv = (TextView) view.findViewById(R.id.bitcoin);
if (!TextUtils.isEmpty(getApp().bitcoinAddr))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Litecoin
tv = (TextView) view.findViewById(R.id.litecoin);
if (!TextUtils.isEmpty(getApp().litecoinAddr))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Flattr
tv = (TextView) view.findViewById(R.id.flattr);
if (!TextUtils.isEmpty(getApp().flattrID))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Categories TextView
final TextView categories = (TextView) view.findViewById(R.id.categories);
if (prefs.expertMode() && getApp().categories != null)
categories.setText(getApp().categories.toString().replaceAll(",", ", "));
else
categories.setVisibility(View.GONE);
Apk curApk = null;
for (int i = 0; i < getApks().getCount(); i++) {
final Apk apk = getApks().getItem(i);
if (apk.vercode == getApp().suggestedVercode) {
curApk = apk;
break;
}
}
// Expandable permissions
ll_view_more_permissions = (LinearLayout) view.findViewById(R.id.ll_permissions);
final TextView permissionHeader = (TextView) view.findViewById(R.id.permissions);
final TextView permissionListView = (TextView) view.findViewById(R.id.permissions_list);
permissionListView.setVisibility(View.GONE);
view_all_permissions = true;
final boolean curApkCompatible = curApk != null && curApk.compatible;
if (!getApks().isEmpty() && (curApkCompatible || prefs.showIncompatibleVersions())) {
permissionHeader.setText(getString(R.string.permissions_for_long, getApks().getItem(0).version));
permissionHeader.setCompoundDrawablesWithIntrinsicBounds(null, null, getActivity().getResources().getDrawable(R.drawable.ic_expand_more_grey600), null);
ll_view_more_permissions.setOnClickListener(expander_permissions);
permissionHeader.setOnClickListener(expander_permissions);
} else {
permissionHeader.setVisibility(View.GONE);
permissionHeader.setCompoundDrawables(null, null, null, null);
}
// Anti features
final TextView antiFeaturesView = (TextView) view.findViewById(R.id.antifeatures);
if (getApp().antiFeatures != null) {
StringBuilder sb = new StringBuilder();
for (final String af : getApp().antiFeatures) {
final String afdesc = descAntiFeature(af);
if (afdesc != null) {
sb.append("\t• ").append(afdesc).append('\n');
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
antiFeaturesView.setText(sb.toString());
} else { } else {
antiFeaturesView.setVisibility(View.GONE); layout_links_content.setVisibility(View.GONE);
linksHeader.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(getActivity(), R.drawable.ic_website), null, ContextCompat.getDrawable(getActivity(), R.drawable.ic_expand_more_grey600), null);
} }
} else {
antiFeaturesView.setVisibility(View.GONE);
} }
};
updateViews(view);
}
private final View.OnClickListener mOnClickListener = new View.OnClickListener() { private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
@ -1317,68 +1185,200 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
private final View.OnClickListener expander_description = new View.OnClickListener() { private final View.OnClickListener expander_description = new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
final TextView description = (TextView) ll_view_more_description.findViewById(R.id.description); final TextView description = (TextView) ll_view_more_description.findViewById(R.id.description);
final ImageView view_more_permissions = (ImageView) ll_view_more_description.findViewById(R.id.view_more_description); final TextView view_more_permissions = (TextView)ll_view_more_description.findViewById(R.id.view_more_description);
if (view_all_description) { if (view_all_description) {
description.setMaxLines(Integer.MAX_VALUE); description.setMaxLines(Integer.MAX_VALUE);
view_more_permissions.setImageResource(R.drawable.ic_expand_less_grey600); view_more_permissions.setText(getString(R.string.less));
} else { } else {
description.setMaxLines(MAX_LINES); description.setMaxLines(MAX_LINES);
view_more_permissions.setImageResource(R.drawable.ic_expand_more_grey600); description.setEllipsize(TextUtils.TruncateAt.MARQUEE);
view_more_permissions.setText(R.string.more);
} }
view_all_description ^= true; view_all_description ^= true;
} }
}; };
private final View.OnClickListener expander_information = new View.OnClickListener() { private void setupView(final View view) {
public void onClick(View v) { // Expandable description
final TextView informationHeader = (TextView) ll_view_more_information.findViewById(R.id.information); final TextView description = (TextView) view.findViewById(R.id.description);
final LinearLayout information_content = (LinearLayout) ll_view_more_information.findViewById(R.id.ll_information_content); final Spanned desc = Html.fromHtml(getApp().description, null, new Utils.HtmlTagHandler());
if (!view_all_information) { description.setMovementMethod(SafeLinkMovementMethod.getInstance(getActivity()));
information_content.setVisibility(View.GONE); description.setText(trimNewlines(desc));
informationHeader.setCompoundDrawablesWithIntrinsicBounds(null, null, getActivity().getResources().getDrawable(R.drawable.ic_expand_more_grey600), null); final View view_more_description = view.findViewById(R.id.view_more_description);
} else { description.post(new Runnable() {
information_content.setVisibility(View.VISIBLE); @Override
informationHeader.setCompoundDrawablesWithIntrinsicBounds(null, null, getActivity().getResources().getDrawable(R.drawable.ic_expand_less_grey600), null); public void run() {
} // If description has more than five lines
view_all_information ^= true; if (description.getLineCount() > MAX_LINES) {
} description.setMaxLines(MAX_LINES);
}; description.setEllipsize(TextUtils.TruncateAt.MARQUEE);
description.setOnClickListener(expander_description);
view_all_description = true;
private final View.OnClickListener expander_permissions = new View.OnClickListener() { ll_view_more_description = (LinearLayout) view.findViewById(R.id.ll_description);
public void onClick(View v) { ll_view_more_description.setOnClickListener(expander_description);
final TextView permissionHeader = (TextView) ll_view_more_permissions.findViewById(R.id.permissions);
final TextView permissionListView = (TextView) ll_view_more_permissions.findViewById(R.id.permissions_list); view_more_description.setOnClickListener(expander_description);
if (!view_all_permissions) {
permissionListView.setVisibility(View.GONE);
permissionHeader.setCompoundDrawablesWithIntrinsicBounds(null, null, getActivity().getResources().getDrawable(R.drawable.ic_expand_more_grey600), null);
} else {
CommaSeparatedList permsList = getApks().getItem(0).permissions;
if (permsList == null) {
permissionListView.setText(R.string.no_permissions);
} else { } else {
Iterator<String> permissions = permsList.iterator(); view_more_description.setVisibility(View.GONE);
StringBuilder sb = new StringBuilder();
while (permissions.hasNext()) {
final String permissionName = permissions.next();
try {
final Permission permission = new Permission(getActivity(), permissionName);
// TODO: Make this list RTL friendly
sb.append("\t• ").append(permission.getName()).append('\n');
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Permission not yet available: " + permissionName);
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
permissionListView.setText(sb.toString());
} }
permissionListView.setVisibility(View.VISIBLE);
permissionHeader.setCompoundDrawablesWithIntrinsicBounds(null, null, getActivity().getResources().getDrawable(R.drawable.ic_expand_less_grey600), null);
} }
view_all_permissions ^= true; });
// App ID
final TextView appIdView = (TextView) view.findViewById(R.id.appid);
if (prefs.expertMode())
appIdView.setText(getApp().id);
else
appIdView.setVisibility(View.GONE);
// Summary
final TextView summaryView = (TextView) view.findViewById(R.id.summary);
summaryView.setText(getApp().summary);
layout_links = (ViewGroup) view.findViewById(R.id.ll_information);
layout_links_content = (ViewGroup) layout_links.findViewById(R.id.ll_information_content);
final TextView linksHeader = (TextView) view.findViewById(R.id.information);
linksHeader.setOnClickListener(expander_links);
// Website button
View tv = view.findViewById(R.id.website);
if (!TextUtils.isEmpty(getApp().webURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Source button
tv = view.findViewById(R.id.source);
if (!TextUtils.isEmpty(getApp().sourceURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Issues button
tv = view.findViewById(R.id.issues);
if (!TextUtils.isEmpty(getApp().trackerURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Changelog button
tv = view.findViewById(R.id.changelog);
if (!TextUtils.isEmpty(getApp().changelogURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Donate button
tv = view.findViewById(R.id.donate);
if (!TextUtils.isEmpty(getApp().donateURL))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Bitcoin
tv = view.findViewById(R.id.bitcoin);
if (!TextUtils.isEmpty(getApp().bitcoinAddr))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Litecoin
tv = view.findViewById(R.id.litecoin);
if (!TextUtils.isEmpty(getApp().litecoinAddr))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Flattr
tv = view.findViewById(R.id.flattr);
if (!TextUtils.isEmpty(getApp().flattrID))
tv.setOnClickListener(mOnClickListener);
else
tv.setVisibility(View.GONE);
// Categories TextView
final TextView categories = (TextView) view.findViewById(R.id.categories);
if (prefs.expertMode() && getApp().categories != null)
categories.setText(getApp().categories.toString().replaceAll(",", ", "));
else
categories.setVisibility(View.GONE);
Apk curApk = null;
for (int i = 0; i < getApks().getCount(); i++) {
final Apk apk = getApks().getItem(i);
if (apk.vercode == getApp().suggestedVercode) {
curApk = apk;
break;
}
} }
};
// Expandable permissions
ll_view_more_permissions = (LinearLayout) view.findViewById(R.id.ll_permissions);
final TextView permissionHeader = (TextView) view.findViewById(R.id.permissions);
final boolean curApkCompatible = curApk != null && curApk.compatible;
if (!getApks().isEmpty() && (curApkCompatible || prefs.showIncompatibleVersions())) {
// build and set the string once
buildPermissionInfo();
permissionHeader.setOnClickListener(expander_permissions);
} else {
permissionHeader.setVisibility(View.GONE);
}
// Anti features
final TextView antiFeaturesView = (TextView) view.findViewById(R.id.antifeatures);
if (getApp().antiFeatures != null) {
StringBuilder sb = new StringBuilder();
for (final String af : getApp().antiFeatures) {
final String afdesc = descAntiFeature(af);
if (afdesc != null) {
sb.append("\t• ").append(afdesc).append('\n');
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
antiFeaturesView.setText(sb.toString());
} else {
antiFeaturesView.setVisibility(View.GONE);
}
} else {
antiFeaturesView.setVisibility(View.GONE);
}
updateViews(view);
}
private void buildPermissionInfo() {
final TextView permissionListView = (TextView) ll_view_more_permissions.findViewById(R.id.permissions_list);
CommaSeparatedList permsList = getApks().getItem(0).permissions;
if (permsList == null) {
permissionListView.setText(R.string.no_permissions);
} else {
Iterator<String> permissions = permsList.iterator();
StringBuilder sb = new StringBuilder();
while (permissions.hasNext()) {
final String permissionName = permissions.next();
try {
final Permission permission = new Permission(getActivity(), permissionName);
// TODO: Make this list RTL friendly
sb.append("\t• ").append(permission.getName()).append('\n');
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Permission not yet available: " + permissionName);
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
permissionListView.setText(sb.toString());
} else {
permissionListView.setText(R.string.no_permissions);
}
}
}
private String descAntiFeature(String af) { private String descAntiFeature(String af) {
switch (af) { switch (af) {