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