Merge branch 'improvements-to-update-workflow' into 'master'
Improvements to update workflow Closes #922 See merge request !468
This commit is contained in:
commit
49f7248d45
@ -371,7 +371,7 @@ class NotificationHelper {
|
|||||||
|
|
||||||
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED);
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED);
|
||||||
intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getUniqueKey());
|
intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getUniqueKey());
|
||||||
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, 0);
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
builder.setDeleteIntent(piDeleted);
|
builder.setDeleteIntent(piDeleted);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
@ -429,7 +429,7 @@ class NotificationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED);
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED);
|
||||||
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, 0);
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
builder.setDeleteIntent(piDeleted);
|
builder.setDeleteIntent(piDeleted);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
@ -456,7 +456,7 @@ class NotificationHelper {
|
|||||||
|
|
||||||
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED);
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED);
|
||||||
intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getUniqueKey());
|
intentDeleted.putExtra(EXTRA_NOTIFICATION_KEY, entry.getUniqueKey());
|
||||||
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, 0);
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
builder.setDeleteIntent(piDeleted);
|
builder.setDeleteIntent(piDeleted);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
@ -484,7 +484,7 @@ class NotificationHelper {
|
|||||||
|
|
||||||
// Intent to open main app list
|
// Intent to open main app list
|
||||||
Intent intentObject = new Intent(context, MainActivity.class);
|
Intent intentObject = new Intent(context, MainActivity.class);
|
||||||
PendingIntent piAction = PendingIntent.getActivity(context, 0, intentObject, 0);
|
PendingIntent piAction = PendingIntent.getActivity(context, 0, intentObject, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
NotificationCompat.Builder builder =
|
NotificationCompat.Builder builder =
|
||||||
new NotificationCompat.Builder(context)
|
new NotificationCompat.Builder(context)
|
||||||
@ -501,7 +501,7 @@ class NotificationHelper {
|
|||||||
.setGroupSummary(true);
|
.setGroupSummary(true);
|
||||||
}
|
}
|
||||||
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED);
|
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_ALL_INSTALLED_CLEARED);
|
||||||
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, 0);
|
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
builder.setDeleteIntent(piDeleted);
|
builder.setDeleteIntent(piDeleted);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import android.app.PendingIntent;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.graphics.Outline;
|
import android.graphics.Outline;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -96,7 +97,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
installButton = (ImageView) itemView.findViewById(R.id.install);
|
installButton = (ImageView) itemView.findViewById(R.id.install);
|
||||||
if (installButton != null) {
|
if (installButton != null) {
|
||||||
installButton.setOnClickListener(onInstallClicked);
|
installButton.setOnClickListener(onActionClicked);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
installButton.setOutlineProvider(new ViewOutlineProvider() {
|
installButton.setOutlineProvider(new ViewOutlineProvider() {
|
||||||
@ -126,7 +127,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
actionButton = (Button) itemView.findViewById(R.id.action_button);
|
actionButton = (Button) itemView.findViewById(R.id.action_button);
|
||||||
|
|
||||||
if (actionButton != null) {
|
if (actionButton != null) {
|
||||||
actionButton.setOnClickListener(onInstallClicked);
|
actionButton.setOnClickListener(onActionClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancelButton != null) {
|
if (cancelButton != null) {
|
||||||
@ -149,9 +150,11 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(activity.getApplicationContext());
|
final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(activity.getApplicationContext());
|
||||||
broadcastManager.unregisterReceiver(onDownloadProgress);
|
broadcastManager.unregisterReceiver(onDownloadProgress);
|
||||||
broadcastManager.unregisterReceiver(onInstallAction);
|
broadcastManager.unregisterReceiver(onInstallAction);
|
||||||
|
broadcastManager.unregisterReceiver(onStatusRemoved);
|
||||||
|
|
||||||
broadcastManager.registerReceiver(onDownloadProgress, DownloaderService.getIntentFilter(currentAppDownloadUrl));
|
broadcastManager.registerReceiver(onDownloadProgress, DownloaderService.getIntentFilter(currentAppDownloadUrl));
|
||||||
broadcastManager.registerReceiver(onInstallAction, Installer.getInstallIntentFilter(Uri.parse(currentAppDownloadUrl)));
|
broadcastManager.registerReceiver(onInstallAction, Installer.getInstallIntentFilter(Uri.parse(currentAppDownloadUrl)));
|
||||||
|
broadcastManager.registerReceiver(onStatusRemoved, new IntentFilter(AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED));
|
||||||
|
|
||||||
configureAppName(app);
|
configureAppName(app);
|
||||||
configureStatusText(app);
|
configureStatusText(app);
|
||||||
@ -255,14 +258,17 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries the {@link AppUpdateStatusManager} and asks if the app was just successfully installed.
|
* Queries the {@link AppUpdateStatusManager} and asks if the app was just successfully installed.
|
||||||
|
* For convenience, returns the {@link org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus}
|
||||||
|
* object if it was sucessfully installed, or null otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean wasSuccessfullyInstalled(@NonNull App app) {
|
@Nullable
|
||||||
|
private AppUpdateStatusManager.AppUpdateStatus wasSuccessfullyInstalled(@NonNull App app) {
|
||||||
for (AppUpdateStatusManager.AppUpdateStatus appStatus : AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName)) {
|
for (AppUpdateStatusManager.AppUpdateStatus appStatus : AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName)) {
|
||||||
if (appStatus.status == AppUpdateStatusManager.Status.Installed) {
|
if (appStatus.status == AppUpdateStatusManager.Status.Installed) {
|
||||||
return true;
|
return appStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,7 +294,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
} else if (isDownloading(app)) {
|
} else if (isDownloading(app)) {
|
||||||
name.setText(activity.getString(R.string.app_list__name__downloading_in_progress, app.name));
|
name.setText(activity.getString(R.string.app_list__name__downloading_in_progress, app.name));
|
||||||
} else if (wasSuccessfullyInstalled(app)) {
|
} else if (wasSuccessfullyInstalled(app) != null) {
|
||||||
name.setText(activity.getString(R.string.app_list__name__successfully_installed, app.name));
|
name.setText(activity.getString(R.string.app_list__name__successfully_installed, app.name));
|
||||||
} else {
|
} else {
|
||||||
name.setText(Utils.formatAppNameAndSummary(app.name, app.summary));
|
name.setText(Utils.formatAppNameAndSummary(app.name, app.summary));
|
||||||
@ -305,15 +311,18 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isReadyToInstall(app)) {
|
actionButton.setVisibility(View.VISIBLE);
|
||||||
actionButton.setVisibility(View.GONE);
|
|
||||||
} else {
|
if (wasSuccessfullyInstalled(app) != null) {
|
||||||
actionButton.setVisibility(View.VISIBLE);
|
actionButton.setText(R.string.menu_launch);
|
||||||
|
} else if (isReadyToInstall(app)) {
|
||||||
if (app.isInstalled()) {
|
if (app.isInstalled()) {
|
||||||
actionButton.setText(R.string.app__install_downloaded_update);
|
actionButton.setText(R.string.app__install_downloaded_update);
|
||||||
} else {
|
} else {
|
||||||
actionButton.setText(R.string.menu_install);
|
actionButton.setText(R.string.menu_install);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
actionButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,9 +338,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isReadyToInstall(app)) {
|
if (isReadyToInstall(app)) {
|
||||||
installButton.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_download_complete));
|
installButton.setVisibility(View.GONE);
|
||||||
installButton.setVisibility(View.VISIBLE);
|
|
||||||
// TODO: If in the downloading phase, then need to reflect that instead of this "download complete" icon.
|
|
||||||
} else {
|
} else {
|
||||||
boolean installable = app.canAndWantToUpdate(activity) || !app.isInstalled();
|
boolean installable = app.canAndWantToUpdate(activity) || !app.isInstalled();
|
||||||
boolean shouldAllow = app.compatible && !app.isFiltered();
|
boolean shouldAllow = app.compatible && !app.isFiltered();
|
||||||
@ -386,7 +393,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
private void onDownloadComplete() {
|
private void onDownloadComplete() {
|
||||||
if (installButton != null) {
|
if (installButton != null) {
|
||||||
installButton.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_download_complete));
|
installButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progressBar != null) {
|
if (progressBar != null) {
|
||||||
@ -473,14 +480,47 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the app goes from "Successfully installed" to anything else, then reset the action button
|
||||||
|
* and the app label text to whatever they should be.
|
||||||
|
*/
|
||||||
|
private final BroadcastReceiver onStatusRemoved = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (currentApp == null || currentAppDownloadUrl == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TextUtils.equals(intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL), currentAppDownloadUrl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
configureAppName(currentApp);
|
||||||
|
configureActionButton(currentApp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@SuppressWarnings("FieldCanBeLocal")
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private final View.OnClickListener onInstallClicked = new View.OnClickListener() {
|
private final View.OnClickListener onActionClicked = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (currentApp == null) {
|
if (currentApp == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When the button says "Run", then launch the app.
|
||||||
|
AppUpdateStatusManager.AppUpdateStatus successfullyInstalledStatus = wasSuccessfullyInstalled(currentApp);
|
||||||
|
if (successfullyInstalledStatus != null) {
|
||||||
|
Intent intent = activity.getPackageManager().getLaunchIntentForPackage(currentApp.packageName);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
|
||||||
|
// Once it is explicitly launched by the user, then we can pretty much forget about
|
||||||
|
// any sort of notification that the app was successfully installed. It should be
|
||||||
|
// apparent to the user because they just launched it.
|
||||||
|
AppUpdateStatusManager.getInstance(activity).removeApk(successfullyInstalledStatus.getUniqueKey());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final Apk suggestedApk = ApkProvider.Helper.findApkFromAnyRepo(activity, currentApp.packageName, currentApp.suggestedVersionCode);
|
final Apk suggestedApk = ApkProvider.Helper.findApkFromAnyRepo(activity, currentApp.packageName, currentApp.suggestedVersionCode);
|
||||||
|
|
||||||
if (isReadyToInstall(currentApp)) {
|
if (isReadyToInstall(currentApp)) {
|
||||||
|
@ -316,7 +316,7 @@ public class UpdatesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||||||
|
|
||||||
// After adding the new item to our list (somewhere) we can then look it back up again in
|
// After adding the new item to our list (somewhere) we can then look it back up again in
|
||||||
// order to notify the recycler view and scroll to that item.
|
// order to notify the recycler view and scroll to that item.
|
||||||
int positionOfNewApp = 0;
|
int positionOfNewApp = -1;
|
||||||
for (int i = 0; i < appsToShowStatus.size(); i++) {
|
for (int i = 0; i < appsToShowStatus.size(); i++) {
|
||||||
if (TextUtils.equals(appsToShowStatus.get(i).status.getUniqueKey(), apkUrl)) {
|
if (TextUtils.equals(appsToShowStatus.get(i).status.getUniqueKey(), apkUrl)) {
|
||||||
positionOfNewApp = i;
|
positionOfNewApp = i;
|
||||||
@ -324,17 +324,19 @@ public class UpdatesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyItemInserted(positionOfNewApp);
|
if (positionOfNewApp != -1) {
|
||||||
|
notifyItemInserted(positionOfNewApp);
|
||||||
|
|
||||||
if (recyclerView != null) {
|
if (recyclerView != null) {
|
||||||
recyclerView.smoothScrollToPosition(positionOfNewApp);
|
recyclerView.smoothScrollToPosition(positionOfNewApp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAppStatusRemoved(String apkUrl) {
|
private void onAppStatusRemoved(String apkUrl) {
|
||||||
// Find out where the item is in our internal data structure, so that we can remove it and
|
// Find out where the item is in our internal data structure, so that we can remove it and
|
||||||
// also notify the recycler view appropriately.
|
// also notify the recycler view appropriately.
|
||||||
int positionOfOldApp = 0;
|
int positionOfOldApp = -1;
|
||||||
for (int i = 0; i < appsToShowStatus.size(); i++) {
|
for (int i = 0; i < appsToShowStatus.size(); i++) {
|
||||||
if (TextUtils.equals(appsToShowStatus.get(i).status.getUniqueKey(), apkUrl)) {
|
if (TextUtils.equals(appsToShowStatus.get(i).status.getUniqueKey(), apkUrl)) {
|
||||||
positionOfOldApp = i;
|
positionOfOldApp = i;
|
||||||
@ -342,10 +344,12 @@ public class UpdatesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appsToShowStatus.remove(positionOfOldApp);
|
if (positionOfOldApp != -1) {
|
||||||
|
appsToShowStatus.remove(positionOfOldApp);
|
||||||
|
|
||||||
populateItems();
|
populateItems();
|
||||||
notifyItemRemoved(positionOfOldApp);
|
notifyItemRemoved(positionOfOldApp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BroadcastReceiver receiverAppStatusChanges = new BroadcastReceiver() {
|
private final BroadcastReceiver receiverAppStatusChanges = new BroadcastReceiver() {
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="90dp"
|
|
||||||
android:height="90dp"
|
|
||||||
android:viewportWidth="90.0"
|
|
||||||
android:viewportHeight="90.0">
|
|
||||||
<path
|
|
||||||
android:pathData="m45,9.73c19.49,0 35.27,15.78 35.27,35.27 0,19.49 -15.78,35.27 -35.27,35.27 -19.49,0 -35.27,-15.78 -35.27,-35.27 0,-19.49 15.78,-35.27 35.27,-35.27z"
|
|
||||||
android:strokeLineCap="butt"
|
|
||||||
android:fillAlpha="1"
|
|
||||||
android:strokeColor="#00000000"
|
|
||||||
android:fillColor="#ffffff"
|
|
||||||
android:strokeWidth="2"
|
|
||||||
android:strokeLineJoin="miter"
|
|
||||||
android:strokeAlpha="1"/>
|
|
||||||
<path
|
|
||||||
android:pathData="m45,7.73c-2.14,0 -4.24,0.19 -6.29,0.54l0.44,1.95c1.9,-0.32 3.86,-0.49 5.85,-0.49 19.49,0 35.27,15.78 35.27,35.27 0,19.49 -15.78,35.27 -35.27,35.27 -19.49,0 -35.27,-15.78 -35.27,-35.27 0,-1.94 0.16,-3.85 0.46,-5.7l-1.97,-0.35c-0.32,1.97 -0.5,3.99 -0.5,6.05 0,20.57 16.7,37.27 37.27,37.27 20.57,0 37.27,-16.7 37.27,-37.27 0,-20.57 -16.7,-37.27 -37.27,-37.27zM30.57,10.64c-3,1.26 -5.8,2.92 -8.34,4.88l1.26,1.53c2.41,-1.86 5.07,-3.42 7.92,-4.61l-0.85,-1.81zM16.08,21.52c-2.24,2.75 -4.09,5.82 -5.47,9.14l1.84,0.76c1.31,-3.15 3.07,-6.06 5.19,-8.67l-1.56,-1.23z"
|
|
||||||
android:strokeLineCap="butt"
|
|
||||||
android:fillAlpha="1"
|
|
||||||
android:strokeColor="#00000000"
|
|
||||||
android:fillColor="#0066cc"
|
|
||||||
android:strokeWidth="2"
|
|
||||||
android:strokeLineJoin="miter"
|
|
||||||
android:strokeAlpha="1"/>
|
|
||||||
<path
|
|
||||||
android:pathData="m59.21,32.08a2.5,2.5 0,0 0,-1.72 0.76l-18.12,18.12 -8.09,-8.09a2.5,2.5 0,1 0,-3.54 3.54l9.85,9.86a2.5,2.5 0,0 0,3.54 0l19.89,-19.89a2.5,2.5 0,0 0,-1.82 -4.29z"
|
|
||||||
android:strokeLineCap="round"
|
|
||||||
android:fillAlpha="1"
|
|
||||||
android:strokeColor="#00000000"
|
|
||||||
android:fillColor="#0066cc"
|
|
||||||
android:strokeWidth="5"
|
|
||||||
android:strokeLineJoin="round"
|
|
||||||
android:strokeAlpha="1"/>
|
|
||||||
</vector>
|
|
@ -36,7 +36,7 @@
|
|||||||
app:layout_constraintTop_toTopOf="@+id/icon"
|
app:layout_constraintTop_toTopOf="@+id/icon"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/install"
|
app:layout_constraintEnd_toStartOf="@+id/buttons"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginRight="8dp" />
|
android:layout_marginRight="8dp" />
|
||||||
|
|
||||||
@ -57,18 +57,34 @@
|
|||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="8dp" />
|
android:layout_marginLeft="8dp" />
|
||||||
|
|
||||||
<ImageView
|
<FrameLayout
|
||||||
android:id="@+id/install"
|
android:id="@+id/buttons"
|
||||||
tools:src="@drawable/ic_download"
|
android:layout_width="wrap_content"
|
||||||
android:scaleType="fitXY"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/menu_install"
|
|
||||||
android:layout_width="64dp"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:elevation="2dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/icon" />
|
app:layout_constraintTop_toTopOf="@+id/icon">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/install"
|
||||||
|
tools:src="@drawable/ic_download"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:contentDescription="@string/menu_install"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:padding="4dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/action_button"
|
||||||
|
style="@style/DetailsPrimaryButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
tools:text="Update" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
@ -55,8 +55,22 @@
|
|||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@+id/action_button"
|
||||||
app:layout_constraintTop_toTopOf="@+id/icon"
|
app:layout_constraintTop_toTopOf="@+id/icon"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/icon" />
|
app:layout_constraintBottom_toBottomOf="@+id/icon" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/action_button"
|
||||||
|
style="@style/DetailsPrimaryButtonStyleSmall"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Update" />
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
Loading…
x
Reference in New Issue
Block a user