mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-04-19 17:17:04 -04:00
W.I.P: progress reader rewrite
This commit is contained in:
@@ -30,10 +30,8 @@
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:label="@string/app_short_name"
|
||||
android:name=".LauncherActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation">
|
||||
android:name=".LauncherActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.kdt.mcgui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
@@ -16,8 +17,11 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import net.kdt.pojavlaunch.R;
|
||||
import net.kdt.pojavlaunch.extra.ExtraCore;
|
||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||
import net.kdt.pojavlaunch.progresskeeper.ProgressListener;
|
||||
import net.kdt.pojavlaunch.services.ProgressService;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/** Class staring at specific values and automatically show something if the progress is present
|
||||
@@ -47,88 +51,38 @@ public class ProgressLayout extends ConstraintLayout implements View.OnClickList
|
||||
init();
|
||||
}
|
||||
|
||||
private int mActiveProcesses = 0;
|
||||
private final ArrayMap<String, TextProgressBar> mMap = new ArrayMap<>();
|
||||
private final ArrayList<LayoutProgressListener> mMap = new ArrayList<>();
|
||||
private LinearLayout mLinearLayout;
|
||||
private TextView mTaskNumberDisplayer;
|
||||
private ImageView mFlipArrow;
|
||||
private final Runnable mCheckProgressRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for(String progressKey : mMap.keySet()){
|
||||
if(progressKey == null) continue; //TODO check wtf does this
|
||||
|
||||
Object object = ExtraCore.consumeValue(progressKey);
|
||||
|
||||
if(object != null){
|
||||
String[] progressStuff = ((String) object).split("¤");
|
||||
int progress = Integer.parseInt(progressStuff[0]);
|
||||
int resourceString = Integer.parseInt(progressStuff[1]);
|
||||
|
||||
// Prepare the progressbar
|
||||
if(mMap.get(progressKey) == null){
|
||||
TextProgressBar textView = new TextProgressBar(getContext());
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, getResources().getDimensionPixelOffset(R.dimen._20sdp));
|
||||
params.bottomMargin = getResources().getDimensionPixelOffset(R.dimen._6sdp);
|
||||
|
||||
mLinearLayout.addView(textView, params);
|
||||
mMap.put(progressKey, textView);
|
||||
mActiveProcesses++;
|
||||
}
|
||||
|
||||
mMap.get(progressKey).setProgress(progress);
|
||||
if(resourceString != -1){
|
||||
// As an optimization, copy array content back 2 indexes instead of creating another object
|
||||
System.arraycopy(progressStuff, 2, progressStuff, 0, progressStuff.length - 2);
|
||||
mMap.get(progressKey).setText(getResources().getString(resourceString, progressStuff));
|
||||
}else{
|
||||
if(progressStuff.length >= 3)
|
||||
mMap.get(progressStuff[2]);
|
||||
}
|
||||
|
||||
|
||||
// Remove when we don't have progress
|
||||
if(progress < 0){
|
||||
if(progress <= -10) // Only remove the observer when it is explicitly told to do so ?
|
||||
mMap.remove(progressKey);
|
||||
|
||||
mLinearLayout.removeView(mMap.get(progressKey));
|
||||
mActiveProcesses--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setVisibility(hasProcesses() ? VISIBLE : GONE);
|
||||
|
||||
mTaskNumberDisplayer.setText(getContext().getString(R.string.progresslayout_tasks_in_progress, mActiveProcesses));
|
||||
postDelayed(this, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
public void observe(String progressKey){
|
||||
mMap.put(progressKey, null);
|
||||
mMap.add(new LayoutProgressListener(progressKey));
|
||||
}
|
||||
|
||||
public boolean hasProcesses(){
|
||||
return mActiveProcesses > 0;
|
||||
return ProgressKeeper.getTaskCount() > 0;
|
||||
}
|
||||
|
||||
public boolean hasProcess(String process){
|
||||
return mMap.get(process) != null;
|
||||
}
|
||||
|
||||
private void init(){
|
||||
inflate(getContext(), R.layout.view_progress, this);
|
||||
mLinearLayout = findViewById(R.id.progress_linear_layout);
|
||||
mTaskNumberDisplayer = findViewById(R.id.progress_textview);
|
||||
mFlipArrow = findViewById(R.id.progress_flip_arrow);
|
||||
postDelayed(mCheckProgressRunnable, 1000);
|
||||
|
||||
setBackgroundColor(getResources().getColor(R.color.background_bottom_bar));
|
||||
setVisibility(GONE);
|
||||
|
||||
ProgressKeeper.addTaskCountListener((tc)->{
|
||||
post(()->{
|
||||
Log.i("ProgressLayout", "tc="+tc);
|
||||
if(tc > 0) {
|
||||
mTaskNumberDisplayer.setText(getContext().getString(R.string.progresslayout_tasks_in_progress, tc));
|
||||
setVisibility(VISIBLE);
|
||||
}else
|
||||
setVisibility(GONE);
|
||||
});
|
||||
});
|
||||
setOnClickListener(this);
|
||||
}
|
||||
|
||||
@@ -138,13 +92,8 @@ public class ProgressLayout extends ConstraintLayout implements View.OnClickList
|
||||
}
|
||||
|
||||
/** Update the text and progress content */
|
||||
public static void setProgress(String progressKey, int progress, @StringRes int resource, String... message){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(String bit : message){
|
||||
builder.append(bit).append("¤");
|
||||
}
|
||||
|
||||
ExtraCore.setValue(progressKey, progress + "¤" + resource + "¤" + builder);
|
||||
public static void setProgress(String progressKey, int progress, @StringRes int resource, Object... message){
|
||||
ProgressKeeper.submitProgress(progressKey, progress, resource, message);
|
||||
}
|
||||
|
||||
/** Update the text and progress content */
|
||||
@@ -162,4 +111,40 @@ public class ProgressLayout extends ConstraintLayout implements View.OnClickList
|
||||
mLinearLayout.setVisibility(mLinearLayout.getVisibility() == GONE ? VISIBLE : GONE);
|
||||
mFlipArrow.setRotation(mLinearLayout.getVisibility() == GONE? 0 : 180);
|
||||
}
|
||||
|
||||
class LayoutProgressListener implements ProgressListener {
|
||||
final String progressKey;
|
||||
final TextProgressBar textView;
|
||||
final LinearLayout.LayoutParams params;
|
||||
public LayoutProgressListener(String progressKey) {
|
||||
this.progressKey = progressKey;
|
||||
textView = new TextProgressBar(getContext());
|
||||
params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, getResources().getDimensionPixelOffset(R.dimen._20sdp));
|
||||
params.bottomMargin = getResources().getDimensionPixelOffset(R.dimen._6sdp);
|
||||
ProgressKeeper.addListener(progressKey, this);
|
||||
}
|
||||
@Override
|
||||
public void onProgressStarted() {
|
||||
post(()-> {
|
||||
Log.i("ProgressLayout", "onProgressStarted");
|
||||
mLinearLayout.addView(textView, params);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressUpdated(int progress, int resid, Object... va) {
|
||||
post(()-> {
|
||||
textView.setProgress(progress);
|
||||
if(resid != -1) textView.setText(getContext().getString(resid, va));
|
||||
else textView.setText("");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressEnded() {
|
||||
post(()-> {
|
||||
mLinearLayout.removeView(textView);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ import net.kdt.pojavlaunch.fragments.SelectAuthFragment;
|
||||
import net.kdt.pojavlaunch.multirt.MultiRTConfigDialog;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
import net.kdt.pojavlaunch.prefs.screens.LauncherPreferenceFragment;
|
||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||
import net.kdt.pojavlaunch.services.ProgressServiceKeeper;
|
||||
import net.kdt.pojavlaunch.tasks.AsyncAssetManager;
|
||||
import net.kdt.pojavlaunch.tasks.AsyncMinecraftDownloader;
|
||||
import net.kdt.pojavlaunch.tasks.AsyncVersionList;
|
||||
@@ -60,6 +62,7 @@ public class LauncherActivity extends BaseActivity {
|
||||
private FragmentContainerView mFragmentView;
|
||||
private ImageButton mSettingsButton, mDeleteAccountButton;
|
||||
private ProgressLayout mProgressLayout;
|
||||
private ProgressServiceKeeper mProgressServiceKeeper;
|
||||
|
||||
/* Allows to switch from one button "type" to another */
|
||||
private final FragmentManager.FragmentLifecycleCallbacks mFragmentCallbackListener = new FragmentManager.FragmentLifecycleCallbacks() {
|
||||
@@ -151,7 +154,7 @@ public class LauncherActivity extends BaseActivity {
|
||||
setContentView(R.layout.activity_pojav_launcher);
|
||||
getWindow().setBackgroundDrawable(null);
|
||||
bindViews();
|
||||
|
||||
ProgressKeeper.addTaskCountListener((mProgressServiceKeeper = new ProgressServiceKeeper(this)));
|
||||
askForStoragePermission(); // Will wait here
|
||||
|
||||
mSettingsButton.setOnClickListener(mSettingButtonListener);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package net.kdt.pojavlaunch.progresskeeper;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class ProgressKeeper {
|
||||
private static final ConcurrentHashMap<String, ConcurrentLinkedQueue<WeakReference<ProgressListener>>> sProgressListeners = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<String, ProgressState> sProgressStates = new ConcurrentHashMap<>();
|
||||
private static final ArrayList<WeakReference<TaskCountListener>> sTaskCountListeners = new ArrayList<>();
|
||||
|
||||
public static void submitProgress(String progressRecord, int progress, int resid, Object... va) {
|
||||
ProgressState progressState = sProgressStates.get(progressRecord);
|
||||
boolean shouldCallStarted = progressState == null;
|
||||
boolean shouldCallEnded = resid == -1 && progress == -1;
|
||||
if(shouldCallEnded) {
|
||||
shouldCallStarted = false;
|
||||
sProgressStates.remove(progressRecord);
|
||||
updateTaskCount();
|
||||
}else if(shouldCallStarted){
|
||||
sProgressStates.put(progressRecord, (progressState = new ProgressState()));
|
||||
updateTaskCount();
|
||||
}
|
||||
if(progressState != null) {
|
||||
progressState.progress = progress;
|
||||
progressState.resid = resid;
|
||||
progressState.varArg = va;
|
||||
}
|
||||
|
||||
Log.d("ProgressLayout", "shouldCallStarted="+shouldCallStarted+" shouldCallEnded="+shouldCallEnded);
|
||||
ConcurrentLinkedQueue<WeakReference<ProgressListener>> listenerWeakReferenceList = sProgressListeners.get(progressRecord);
|
||||
if(listenerWeakReferenceList != null) {
|
||||
Iterator<WeakReference<ProgressListener>> iterator = listenerWeakReferenceList.iterator();
|
||||
while(iterator.hasNext()) {
|
||||
ProgressListener listener = iterator.next().get();
|
||||
Log.i("ProgressLayout", listener+"");
|
||||
if(listener != null) {
|
||||
if(shouldCallStarted) listener.onProgressStarted();
|
||||
else if(shouldCallEnded) listener.onProgressEnded();
|
||||
else listener.onProgressUpdated(progress, resid, va);
|
||||
} else iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateTaskCount() {
|
||||
Log.i("ProgressKeeper","updateTaskCount()");
|
||||
int count = sProgressStates.size();
|
||||
Iterator<WeakReference<TaskCountListener>> taskCountListeners = sTaskCountListeners.iterator();
|
||||
while(taskCountListeners.hasNext()) {
|
||||
TaskCountListener countListener = taskCountListeners.next().get();
|
||||
if(countListener == null) {
|
||||
Log.i("ProgressKeeper","Swooped a listener");
|
||||
taskCountListeners.remove();
|
||||
}
|
||||
else countListener.onUpdateTaskCount(count);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addListener(String progressRecord, ProgressListener listener) {
|
||||
ProgressState state = sProgressStates.get(progressRecord);
|
||||
if(state != null && (state.resid != -1 || state.progress != -1)) {
|
||||
listener.onProgressStarted();
|
||||
listener.onProgressUpdated(state.progress, state.resid, state.varArg);
|
||||
Log.d("ProgressLayout", "Resubmitting UI state");
|
||||
}else{
|
||||
listener.onProgressEnded();
|
||||
}
|
||||
ConcurrentLinkedQueue<WeakReference<ProgressListener>> listenerWeakReferenceList = sProgressListeners.get(progressRecord);
|
||||
if(listenerWeakReferenceList == null) sProgressListeners.put(progressRecord, (listenerWeakReferenceList = new ConcurrentLinkedQueue<>()));
|
||||
else {
|
||||
Iterator<WeakReference<ProgressListener>> iterator = listenerWeakReferenceList.iterator();
|
||||
while(iterator.hasNext()) {
|
||||
if(iterator.next().get() == null) iterator.remove();
|
||||
}
|
||||
}
|
||||
listenerWeakReferenceList.add(new WeakReference<>(listener));
|
||||
}
|
||||
public static void addTaskCountListener(TaskCountListener listener) {
|
||||
Iterator<WeakReference<TaskCountListener>> taskCountListeners = sTaskCountListeners.iterator();
|
||||
while(taskCountListeners.hasNext()) {
|
||||
TaskCountListener countListener = taskCountListeners.next().get();
|
||||
if(countListener == null){
|
||||
Log.i("ProgressKeeper","Swooped a listener");
|
||||
taskCountListeners.remove();
|
||||
}
|
||||
}
|
||||
listener.onUpdateTaskCount(sProgressStates.size());
|
||||
sTaskCountListeners.add(new WeakReference<>(listener));
|
||||
}
|
||||
public static int getTaskCount() {
|
||||
return sProgressStates.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package net.kdt.pojavlaunch.progresskeeper;
|
||||
|
||||
public interface ProgressListener {
|
||||
void onProgressStarted();
|
||||
void onProgressUpdated(int progress, int resid, Object... va);
|
||||
void onProgressEnded();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package net.kdt.pojavlaunch.progresskeeper;
|
||||
|
||||
public class ProgressState {
|
||||
int progress;
|
||||
int resid;
|
||||
Object[] varArg;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.kdt.pojavlaunch.progresskeeper;
|
||||
|
||||
public interface TaskCountListener {
|
||||
void onUpdateTaskCount(int taskCount);
|
||||
}
|
||||
@@ -5,54 +5,49 @@ import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import net.kdt.pojavlaunch.R;
|
||||
import net.kdt.pojavlaunch.Tools;
|
||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||
import net.kdt.pojavlaunch.progresskeeper.ProgressListener;
|
||||
import net.kdt.pojavlaunch.progresskeeper.TaskCountListener;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Lazy service which allows the process not to get killed.
|
||||
* Can be created from context, can be killed statically
|
||||
*/
|
||||
public class ProgressService extends Service {
|
||||
public class ProgressService extends Service implements TaskCountListener {
|
||||
|
||||
private static WeakReference<Service> sProgressService = new WeakReference<>(null);
|
||||
private static final AtomicInteger sReferenceCount = new AtomicInteger(0);
|
||||
private Handler mainThreadHandler = new Handler();
|
||||
private NotificationManagerCompat notificationManagerCompat;
|
||||
|
||||
/** Simple wrapper to start the service */
|
||||
public static void startService(Context context){
|
||||
Intent intent = new Intent(context, ProgressService.class);
|
||||
if(sReferenceCount.get() < 0) sReferenceCount.set(0);
|
||||
sReferenceCount.getAndIncrement();
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
|
||||
/** Kill the service if it is still running */
|
||||
public static void killService(){
|
||||
Service service = sProgressService.get();
|
||||
int refcnt = sReferenceCount.decrementAndGet();
|
||||
if(service != null && refcnt <= 0) {
|
||||
service.stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationCompat.Builder mNotificationBuilder;
|
||||
public ProgressService(){
|
||||
super();
|
||||
sProgressService = new WeakReference<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
Tools.buildNotificationChannel(getApplicationContext());
|
||||
notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());
|
||||
Intent killIntent = new Intent(getApplicationContext(), ProgressService.class);
|
||||
killIntent.putExtra("kill", true);
|
||||
PendingIntent pendingKillIntent = PendingIntent.getService(this, 0, killIntent, Build.VERSION.SDK_INT >=23 ? PendingIntent.FLAG_IMMUTABLE : 0);
|
||||
@@ -60,16 +55,20 @@ public class ProgressService extends Service {
|
||||
.setContentTitle(getString(R.string.lazy_service_default_title))
|
||||
.addAction(android.R.drawable.ic_menu_close_clear_cancel, getString(R.string.notification_terminate), pendingKillIntent)
|
||||
.setSmallIcon(R.mipmap.ic_launcher_round);
|
||||
ProgressKeeper.addTaskCountListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if(intent != null && intent.getBooleanExtra("kill", false)) {
|
||||
stopSelf(); // otherwise Android tries to restart the service since it "crashed"
|
||||
Process.killProcess(Process.myPid());
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
if(intent != null) {
|
||||
if(intent.getBooleanExtra("kill", false)) {
|
||||
stopSelf(); // otherwise Android tries to restart the service since it "crashed"
|
||||
Process.killProcess(Process.myPid());
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
}
|
||||
mNotificationBuilder.setContentText(getString(R.string.progresslayout_tasks_in_progress, sReferenceCount.get()));
|
||||
Log.d("ProgressService", "Started!");
|
||||
mNotificationBuilder.setContentText(getString(R.string.progresslayout_tasks_in_progress, ProgressKeeper.getTaskCount()));
|
||||
startForeground(1,mNotificationBuilder.build());
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
@@ -79,4 +78,16 @@ public class ProgressService extends Service {
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateTaskCount(int taskCount) {
|
||||
mainThreadHandler.post(()->{
|
||||
if(taskCount < 0) {
|
||||
mNotificationBuilder.setContentText(getString(R.string.progresslayout_tasks_in_progress, taskCount));
|
||||
notificationManagerCompat.notify(1, mNotificationBuilder.build());
|
||||
}else{
|
||||
stopSelf();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.kdt.pojavlaunch.services;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import net.kdt.pojavlaunch.progresskeeper.TaskCountListener;
|
||||
|
||||
public class ProgressServiceKeeper implements TaskCountListener {
|
||||
private Context context;
|
||||
public ProgressServiceKeeper(Context ctx) {
|
||||
this.context = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateTaskCount(int taskCount) {
|
||||
Log.d("ProgressServiceKeeper", taskCount+"");
|
||||
if(taskCount > 0) ProgressService.startService(context);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ public class AsyncAssetManager {
|
||||
// Install the runtime in an async manner, hope for the best
|
||||
String finalRt_version = rt_version;
|
||||
sExecutorService.execute(() -> {
|
||||
|
||||
try {
|
||||
MultiRTUtils.installRuntimeNamedBinpack(
|
||||
am.open("components/jre/universal.tar.xz"),
|
||||
|
||||
@@ -47,13 +47,9 @@ public class AsyncMinecraftDownloader {
|
||||
|
||||
public AsyncMinecraftDownloader(@NonNull Activity activity, JMinecraftVersionList.Version version,
|
||||
@NonNull DoneListener listener){
|
||||
ProgressService.startService(activity);
|
||||
sExecutorService.execute(() -> {
|
||||
|
||||
if(downloadGame(activity, version, version.id))
|
||||
listener.onDownloadDone();
|
||||
|
||||
ProgressService.killService();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
104
app_pojavlauncher/src/main/res/layout-land/fragment_launcher.xml
Normal file
104
app_pojavlauncher/src/main/res/layout-land/fragment_launcher.xml
Normal file
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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/fragment_menu_main"
|
||||
android:gravity="top"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background_app"
|
||||
>
|
||||
|
||||
<com.kdt.mcgui.LauncherMenuButton
|
||||
android:id="@+id/news_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_66sdp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
|
||||
android:text="@string/mcl_tab_news"
|
||||
android:drawableStart="@drawable/ic_menu_news"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
/>
|
||||
|
||||
<com.kdt.mcgui.LauncherMenuButton
|
||||
android:id="@+id/custom_control_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_66sdp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:drawableStart="@drawable/ic_menu_custom_controls"
|
||||
android:text="@string/mcl_option_customcontrol"
|
||||
app:layout_constraintTop_toBottomOf="@id/news_button"
|
||||
|
||||
/>
|
||||
|
||||
<com.kdt.mcgui.LauncherMenuButton
|
||||
android:id="@+id/install_jar_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_66sdp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:drawableStart="@drawable/ic_menu_install_jar"
|
||||
android:text="@string/main_install_jar_file"
|
||||
|
||||
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
||||
/>
|
||||
|
||||
|
||||
<com.kdt.mcgui.mcVersionSpinner
|
||||
android:id="@+id/mc_version_spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/_32sdp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
|
||||
android:background="@android:color/transparent"
|
||||
android:drawableEnd="@drawable/spinner_arrow"
|
||||
app:drawableEndPadding="@dimen/_1sdp"
|
||||
app:drawableEndSize="@dimen/_12sdp"
|
||||
|
||||
app:drawableStartIntegerScaling="true"
|
||||
app:drawableStartSize="@dimen/_36sdp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/edit_profile_button"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/edit_profile_button"
|
||||
android:layout_width="@dimen/_32sdp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="@dimen/_8sdp"
|
||||
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@drawable/ic_edit_profile"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/mc_version_spinner"
|
||||
app:layout_constraintEnd_toStartOf="@+id/play_button"
|
||||
app:layout_constraintTop_toTopOf="@+id/mc_version_spinner" />
|
||||
|
||||
|
||||
<!-- This view is for cosmetic purpose only -->
|
||||
<View
|
||||
android:id="@+id/_background_display_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="-8dp"
|
||||
android:background="@color/background_bottom_bar"
|
||||
|
||||
android:translationZ="-1dp"
|
||||
app:layout_constraintTop_toTopOf="@id/mc_version_spinner" />
|
||||
|
||||
<com.kdt.mcgui.MineButton
|
||||
android:id="@+id/play_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
|
||||
android:layout_marginEnd="@dimen/_8sdp"
|
||||
android:text="@string/main_play"
|
||||
android:textAllCaps="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/mc_version_spinner"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/mc_version_spinner" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
Reference in New Issue
Block a user