Initial work on details view
This commit is contained in:
parent
f355232bd5
commit
34450569b3
@ -404,6 +404,17 @@
|
||||
android:value=".FDroid" />
|
||||
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".AppDetails2"
|
||||
android:label="@string/app_details"
|
||||
android:exported="true"
|
||||
android:parentActivityName=".FDroid"
|
||||
android:theme="@style/AppThemeLight.NoActionBar"
|
||||
android:configChanges="layoutDirection|locale" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".FDroid" />
|
||||
</activity>
|
||||
<activity
|
||||
android:label="@string/menu_settings"
|
||||
android:name=".PreferencesActivity"
|
||||
|
500
app/src/main/java/org/fdroid/fdroid/AppDetails2.java
Normal file
500
app/src/main/java/org/fdroid/fdroid/AppDetails2.java
Normal file
@ -0,0 +1,500 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.widget.TextViewCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.text.AllCapsTransformationMethod;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Html;
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.data.AppProvider;
|
||||
import org.fdroid.fdroid.views.LinearLayoutManagerSnapHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static android.support.v7.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
public class AppDetails2 extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "AppDetails2";
|
||||
|
||||
private App mApp;
|
||||
private RecyclerView mRecyclerView;
|
||||
private AppDetailsRecyclerViewAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_app_details2);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
toolbar.setTitle(""); // Nice and clean toolbar
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
App app = null;
|
||||
String packageName = getPackageNameFromIntent(getIntent());
|
||||
if (!TextUtils.isEmpty(packageName)) {
|
||||
app = AppProvider.Helper.findHighestPriorityMetadata(getContentResolver(), packageName);
|
||||
}
|
||||
setApp(app); // Will call finish if empty or unknown
|
||||
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.rvDetails);
|
||||
mAdapter = new AppDetailsRecyclerViewAdapter(this);
|
||||
LinearLayoutManager lm = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
|
||||
lm.setStackFromEnd(false);
|
||||
mRecyclerView.setLayoutManager(lm);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
private String getPackageNameFromIntent(Intent intent) {
|
||||
if (!intent.hasExtra(AppDetails.EXTRA_APPID)) {
|
||||
Log.e(TAG, "No package name found in the intent!");
|
||||
return null;
|
||||
}
|
||||
return intent.getStringExtra(AppDetails.EXTRA_APPID);
|
||||
}
|
||||
|
||||
/**
|
||||
* If passed null, this will show a message to the user ("Could not find app ..." or something
|
||||
* like that) and then finish the activity.
|
||||
*/
|
||||
private void setApp(App newApp) {
|
||||
if (newApp == null) {
|
||||
Toast.makeText(this, R.string.no_such_app, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mApp = newApp;
|
||||
}
|
||||
|
||||
public class AppDetailsRecyclerViewAdapter
|
||||
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
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<Integer> 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<RecyclerView.ViewHolder> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<Cursor> {
|
||||
|
||||
@ -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
|
||||
|
BIN
app/src/main/res/drawable-mdpi/feature_placeholder.png
Normal file
BIN
app/src/main/res/drawable-mdpi/feature_placeholder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 346 KiB |
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue_dark" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_checked="true">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue_dark" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue_dark" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_checked="true">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@color/fdroid_blue" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="3dp" />
|
||||
<solid android:color="@android:color/white" />
|
||||
<stroke android:color="@color/fdroid_blue" android:width="2dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
46
app/src/main/res/layout/activity_app_details2.xml
Normal file
46
app/src/main/res/layout/activity_app_details2.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="org.fdroid.fdroid.AppDetails2">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/app_bar_height"
|
||||
android:fitsSystemWindows="true"
|
||||
android:theme="@style/AppThemeLight.AppBarOverlay">
|
||||
|
||||
<android.support.design.widget.CollapsingToolbarLayout
|
||||
android:id="@+id/toolbar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
app:contentScrim="?attr/colorPrimary"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backdrop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:fitsSystemWindows="true"
|
||||
android:src="@drawable/feature_placeholder"
|
||||
app:layout_collapseMode="parallax" />
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_collapseMode="pin"
|
||||
app:popupTheme="@style/AppThemeLight.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.CollapsingToolbarLayout>
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_app_details2" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
125
app/src/main/res/layout/app_details2_header.xml
Executable file
125
app/src/main/res/layout/app_details2_header.xml
Executable file
@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:cardBackgroundColor="#efefef"
|
||||
app:cardCornerRadius="3dp"
|
||||
app:cardElevation="3dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:src="@drawable/ic_repo_app_default" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toEndOf="@id/icon"
|
||||
android:layout_toRightOf="@id/icon"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
||||
tools:text="App Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/author"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@id/title"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignRight="@id/title"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_below="@id/title"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="Author" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/icon"
|
||||
android:layout_toEndOf="@id/icon"
|
||||
android:layout_toRightOf="@id/icon"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true">
|
||||
|
||||
<Button
|
||||
android:id="@+id/secondaryButtonView"
|
||||
style="@style/DetailsSecondaryButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="marquee"
|
||||
android:text="THIS IS BUTTON 1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/primaryButtonView"
|
||||
style="@style/DetailsPrimaryButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="marquee"
|
||||
android:text="THIS IS 2" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="This app is awezome"
|
||||
android:scrollbars="none"
|
||||
android:textStyle="bold"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="This is the app description of this awezome app. It can be several lines long, but will be truncated at just a few if it is. A 'read more' button will appear so that you can expand the view and view the full text, if you wish. Yes, it will be blue and beautiful."
|
||||
android:scrollbars="none"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description_more"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
style="@style/DetailsMoreButtonStyle"
|
||||
android:gravity="right|end"
|
||||
android:text="@string/more"
|
||||
tools:text="more" />
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
19
app/src/main/res/layout/app_details2_screenshot_item.xml
Normal file
19
app/src/main/res/layout/app_details2_screenshot_item.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:cardElevation="3dp"
|
||||
app:cardBackgroundColor="#ffffff"
|
||||
android:padding="10dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
>
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
/>
|
||||
</android.support.v7.widget.CardView>
|
7
app/src/main/res/layout/app_details2_screenshots.xml
Normal file
7
app/src/main/res/layout/app_details2_screenshots.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/screenshots"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp">
|
||||
</android.support.v7.widget.RecyclerView>
|
8
app/src/main/res/layout/app_details2_whatsnew.xml
Executable file
8
app/src/main/res/layout/app_details2_whatsnew.xml
Executable 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/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
/>
|
14
app/src/main/res/layout/content_app_details2.xml
Normal file
14
app/src/main/res/layout/content_app_details2.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/rvDetails"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
app:behavior_overlapTop="40dp"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
tools:context="org.fdroid.fdroid.AppDetails2"
|
||||
tools:showIn="@layout/activity_app_details2">
|
||||
</android.support.v7.widget.RecyclerView>
|
@ -18,4 +18,11 @@
|
||||
<item name="android:colorButtonNormal">#04b9e6</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -3,5 +3,10 @@
|
||||
|
||||
<dimen name="layout_horizontal_margin">16dp</dimen>
|
||||
<dimen name="material_listitem_height">48dp</dimen>
|
||||
<dimen name="app_bar_height">180dp</dimen>
|
||||
<!-- "Not selected" items are inset by this value, while the selected one is not -->
|
||||
<dimen name="details_screenshot_margin">16dp</dimen>
|
||||
<!-- The selected item stands out from the background by this elevation -->
|
||||
<dimen name="details_screenshot_selected_elevation">3dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
@ -246,4 +246,13 @@
|
||||
<style name="AppDetailsSubheaderText" parent="AppDetailsSubheaderTextBase" />
|
||||
|
||||
<style name="AppThemeTransparent" parent="@android:style/Theme.NoDisplay" />
|
||||
|
||||
<style name="AppThemeLight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppThemeLight.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
||||
|
26
app/src/main/res/values/styles_detail.xml
Normal file
26
app/src/main/res/values/styles_detail.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="DetailsPrimaryButtonStyle">
|
||||
<item name="android:padding">5dp</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:textColor">#ffffff</item>
|
||||
<item name="android:background">@drawable/button_primary_background_selector</item>
|
||||
</style>
|
||||
|
||||
<style name="DetailsSecondaryButtonStyle">
|
||||
<item name="android:padding">5dp</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:textColor">@color/fdroid_blue</item>
|
||||
<item name="android:background">@drawable/button_secondary_background_selector</item>
|
||||
</style>
|
||||
|
||||
<style name="DetailsMoreButtonStyle">
|
||||
<item name="android:padding">5dp</item>
|
||||
<item name="android:textSize">15sp</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:textColor">@color/fdroid_blue</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user