mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
refactor: remove unused legacy project creator
This commit is contained in:
@@ -1,111 +0,0 @@
|
||||
package com.itsaky.androidide.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.blankj.utilcode.util.ConvertUtils;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.shape.CornerFamily;
|
||||
import com.itsaky.androidide.databinding.LayoutTemplateListItemBinding;
|
||||
import com.itsaky.androidide.models.ProjectTemplate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WizardTemplateAdapter extends RecyclerView.Adapter<WizardTemplateAdapter.ViewHolder> {
|
||||
|
||||
private final List<ProjectTemplate> mItems = new ArrayList<>();
|
||||
private OnItemClickListener mListener;
|
||||
|
||||
public WizardTemplateAdapter() {
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void submitList(@NonNull List<ProjectTemplate> newItems) {
|
||||
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
|
||||
@Override
|
||||
public int getOldListSize() {
|
||||
return mItems.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize() {
|
||||
return newItems.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return Objects.equals(mItems.get(oldItemPosition), newItems.get(newItemPosition));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return Objects.equals(mItems.get(oldItemPosition), newItems.get(newItemPosition));
|
||||
}
|
||||
});
|
||||
mItems.clear();
|
||||
mItems.addAll(newItems);
|
||||
diffResult.dispatchUpdatesTo(this);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutTemplateListItemBinding binding = LayoutTemplateListItemBinding.inflate(
|
||||
LayoutInflater.from(parent.getContext()), parent, false);
|
||||
|
||||
ViewHolder holder = new ViewHolder(binding);
|
||||
binding.getRoot().setOnClickListener(view1 -> {
|
||||
if (mListener != null) {
|
||||
int pos = holder.getBindingAdapterPosition();
|
||||
if (pos != RecyclerView.NO_POSITION) {
|
||||
mListener.onItemClick(mItems.get(pos), pos);
|
||||
}
|
||||
}
|
||||
});
|
||||
return holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
holder.bind(mItems.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mItems.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public final ShapeableImageView icon;
|
||||
public final TextView name;
|
||||
|
||||
public ViewHolder(LayoutTemplateListItemBinding view) {
|
||||
super(view.getRoot());
|
||||
|
||||
icon = view.templateIcon;
|
||||
name = view.templateName;
|
||||
}
|
||||
|
||||
private void bind(ProjectTemplate template) {
|
||||
name.setText(template.getName());
|
||||
icon.setImageResource(template.getImageId());
|
||||
icon.setShapeAppearanceModel(icon.getShapeAppearanceModel()
|
||||
.toBuilder()
|
||||
.setAllCorners(CornerFamily.ROUNDED, ConvertUtils.dp2px(8))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
|
||||
void onItemClick(ProjectTemplate item, int position);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import com.itsaky.androidide.adapters.MainActionsListAdapter
|
||||
import com.itsaky.androidide.app.BaseApplication
|
||||
import com.itsaky.androidide.common.databinding.LayoutDialogProgressBinding
|
||||
import com.itsaky.androidide.databinding.FragmentMainBinding
|
||||
import com.itsaky.androidide.fragments.WizardFragment.OnProjectCreatedListener
|
||||
import com.itsaky.androidide.models.MainScreenAction
|
||||
import com.itsaky.androidide.preferences.databinding.LayoutDialogTextInputBinding
|
||||
import com.itsaky.androidide.resources.R
|
||||
@@ -32,7 +31,7 @@ import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.ProgressMonitor
|
||||
import java.io.File
|
||||
|
||||
class MainFragment : BaseFragment(), OnProjectCreatedListener {
|
||||
class MainFragment : BaseFragment() {
|
||||
|
||||
private val viewModel by viewModels<MainViewModel>(
|
||||
ownerProducer = { requireActivity() })
|
||||
@@ -86,7 +85,7 @@ class MainFragment : BaseFragment(), OnProjectCreatedListener {
|
||||
viewModel.setScreen(MainViewModel.SCREEN_TEMPLATE_LIST)
|
||||
}
|
||||
|
||||
override fun openProject(root: File) {
|
||||
fun openProject(root: File) {
|
||||
(requireActivity() as MainActivity).openProject(root)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,533 +0,0 @@
|
||||
package com.itsaky.androidide.fragments;
|
||||
|
||||
import static com.itsaky.androidide.resources.R.string;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.google.android.material.transition.MaterialFadeThrough;
|
||||
import com.google.android.material.transition.MaterialSharedAxis;
|
||||
import com.itsaky.androidide.adapters.WizardTemplateAdapter;
|
||||
import com.itsaky.androidide.app.IDEApplication;
|
||||
import com.itsaky.androidide.databinding.FragmentWizardBinding;
|
||||
import com.itsaky.androidide.databinding.LayoutLoadingWizardBinding;
|
||||
import com.itsaky.androidide.databinding.SetupFooterBinding;
|
||||
import com.itsaky.androidide.databinding.WizardDetailsBinding;
|
||||
import com.itsaky.androidide.databinding.WizardTemplatesBinding;
|
||||
import com.itsaky.androidide.fragments.sheets.ProgressSheet;
|
||||
import com.itsaky.androidide.managers.PreferenceManager;
|
||||
import com.itsaky.androidide.models.ProjectTemplate;
|
||||
import com.itsaky.androidide.utils.AndroidUtils;
|
||||
import com.itsaky.androidide.utils.DialogUtils;
|
||||
import com.itsaky.androidide.utils.Environment;
|
||||
import com.itsaky.androidide.utils.FileUtil;
|
||||
import com.itsaky.androidide.utils.FlashbarUtilsKt;
|
||||
import com.itsaky.androidide.utils.SingleTextWatcher;
|
||||
import com.itsaky.androidide.viewmodel.WizardViewModel;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WizardFragment extends BaseFragment {
|
||||
|
||||
public static final String TAG = "WizardFragmentTag";
|
||||
public static final String PREF_PACKAGE_DOMAIN_KEY = "pref_package_domain";
|
||||
public static final String PREF_MIN_SDK_INDEX_KEY = "pref_min_sdk_index";
|
||||
public static final String PREF_TERGET_SDK_INDEX_KEY = "pref_target_sdk_index";
|
||||
public static final String PREF_SAVE_PROJECT_DIR_KEY = "pref_save_prohect_dir";
|
||||
|
||||
private FragmentWizardBinding binding;
|
||||
private WizardTemplatesBinding templatesBinding;
|
||||
private WizardDetailsBinding detailsBinding;
|
||||
private WizardTemplateAdapter mAdapter;
|
||||
private LayoutLoadingWizardBinding loadingLayout;
|
||||
private SetupFooterBinding footerBinding;
|
||||
|
||||
private WizardViewModel mViewModel;
|
||||
|
||||
private ProgressSheet mProgressSheet;
|
||||
private ProjectTemplate mCurrentTemplate;
|
||||
private OnProjectCreatedListener mListener;
|
||||
|
||||
private boolean mLast;
|
||||
private final OnBackPressedCallback onBackPressedCallback =
|
||||
new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
onNavigateBack();
|
||||
}
|
||||
};
|
||||
private int minSdkIndex;
|
||||
private int targetSdkIndex;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentWizardBinding.inflate(inflater, container, false);
|
||||
loadingLayout = binding.loadingLayout;
|
||||
templatesBinding = binding.wizardTemplatesLayout;
|
||||
detailsBinding = binding.wizardDetailsLayout;
|
||||
footerBinding = binding.footerLayout;
|
||||
mViewModel = new ViewModelProvider(this).get(WizardViewModel.class);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
requireActivity()
|
||||
.getOnBackPressedDispatcher()
|
||||
.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
||||
|
||||
footerBinding.nextButton.setOnClickListener(v -> onNavigateNext());
|
||||
footerBinding.exitButton.setOnClickListener(v -> onNavigateBack());
|
||||
|
||||
templatesBinding.templateRecyclerview.setLayoutManager(
|
||||
new GridLayoutManager(requireContext(), 3));
|
||||
|
||||
mAdapter = new WizardTemplateAdapter();
|
||||
templatesBinding.templateRecyclerview.setAdapter(mAdapter);
|
||||
|
||||
mViewModel.createTemplatesList();
|
||||
mViewModel.getProjects().observe(getViewLifecycleOwner(), mAdapter::submitList);
|
||||
mViewModel.getLoadingState().observe(getViewLifecycleOwner(), this::toggleLoadingState);
|
||||
|
||||
mViewModel
|
||||
.getStatusMessage()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
(message) -> {
|
||||
if (mProgressSheet == null) {
|
||||
createProgressSheet();
|
||||
}
|
||||
setMessage(message);
|
||||
});
|
||||
|
||||
mViewModel
|
||||
.getErrorState()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
(message) -> {
|
||||
if (mProgressSheet != null && mProgressSheet.isShowing()) {
|
||||
mProgressSheet.dismiss();
|
||||
}
|
||||
FlashbarUtilsKt.flashError(message);
|
||||
});
|
||||
|
||||
mViewModel
|
||||
.getFileCreatedState()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
(file) -> {
|
||||
if (file != null) onSuccess(file);
|
||||
});
|
||||
|
||||
mAdapter.setOnItemClickListener(
|
||||
(item, pos) -> {
|
||||
mCurrentTemplate = item;
|
||||
onNavigateNext();
|
||||
});
|
||||
|
||||
initDetailsView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mViewModel = null;
|
||||
binding = null;
|
||||
loadingLayout = null;
|
||||
templatesBinding = null;
|
||||
detailsBinding = null;
|
||||
footerBinding = null;
|
||||
mAdapter = null;
|
||||
mProgressSheet = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
onBackPressedCallback.setEnabled(false);
|
||||
}
|
||||
|
||||
public void onSuccess(File root) {
|
||||
if (mProgressSheet != null && mProgressSheet.isShowing()) {
|
||||
mProgressSheet.dismiss();
|
||||
}
|
||||
FlashbarUtilsKt.flashSuccess(string.project_created_successfully);
|
||||
|
||||
if (mListener != null) {
|
||||
getParentFragmentManager().popBackStack();
|
||||
mListener.openProject(root);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnProjectCreatedListener(OnProjectCreatedListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
private void toggleLoadingState(boolean loading) {
|
||||
if (loading) {
|
||||
showLoading();
|
||||
} else {
|
||||
showTemplatesView();
|
||||
}
|
||||
}
|
||||
|
||||
private String getSelectedItem(int pos, AutoCompleteTextView view) {
|
||||
return view.getAdapter().getItem(pos).toString();
|
||||
}
|
||||
|
||||
private void showLoading() {
|
||||
TransitionManager.beginDelayedTransition((ViewGroup) requireView(), new MaterialFadeThrough());
|
||||
binding.loadingLayout.getRoot().setVisibility(View.VISIBLE);
|
||||
binding.wizardTemplatesLayout.getRoot().setVisibility(View.GONE);
|
||||
footerBinding.nextButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private int getMinSdk() {
|
||||
return getSdkVersion(detailsBinding.etMinSdk);
|
||||
}
|
||||
|
||||
private int getTargetSdk() {
|
||||
return getSdkVersion(detailsBinding.etTargetSdk);
|
||||
}
|
||||
|
||||
private int getSdkVersion(AutoCompleteTextView view) {
|
||||
try {
|
||||
String sdk =
|
||||
view.getText()
|
||||
.toString()
|
||||
.substring("API".length() + 1, "API".length() + 3); // at least 2 digits
|
||||
return Integer.parseInt(sdk);
|
||||
} catch (Exception e) {
|
||||
FlashbarUtilsKt.flashError(e.getMessage());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private boolean validateDetails() {
|
||||
|
||||
verifyAppName(detailsBinding.tilAppName.getEditText().getText(), false);
|
||||
verifyPackageName(detailsBinding.tilPackageName.getEditText().getText());
|
||||
if (detailsBinding.tilPackageName.isErrorEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (detailsBinding.tilAppName.isErrorEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mCurrentTemplate != null;
|
||||
}
|
||||
|
||||
private void createNewProject() {
|
||||
if (validateDetails()) {
|
||||
final String appName =
|
||||
Objects.requireNonNull(detailsBinding.etAppName).getText().toString().trim();
|
||||
final String packageName =
|
||||
Objects.requireNonNull(detailsBinding.etPackageName).getText().toString().trim();
|
||||
final int minSdk = getMinSdk();
|
||||
final int targetSdk = getTargetSdk();
|
||||
final String savePath = detailsBinding.etSaveLocation.getText().toString().trim();
|
||||
final String projectLanguage = detailsBinding.etLanguage.getText().toString();
|
||||
final String cppToolChain =
|
||||
getCppToolchans().get(detailsBinding.etToolchain.getText().toString());
|
||||
|
||||
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
|
||||
manager.putInt(PREF_MIN_SDK_INDEX_KEY, minSdkIndex);
|
||||
manager.putInt(PREF_TERGET_SDK_INDEX_KEY, targetSdkIndex);
|
||||
manager.putString(PREF_PACKAGE_DOMAIN_KEY, AndroidUtils.getPackageDomain(packageName));
|
||||
mViewModel.createProject(
|
||||
mCurrentTemplate,
|
||||
appName,
|
||||
packageName,
|
||||
minSdk,
|
||||
targetSdk,
|
||||
projectLanguage,
|
||||
cppToolChain,
|
||||
savePath);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getSdks() {
|
||||
return Arrays.asList(
|
||||
"API 16: Android 4.0 (Ice Cream Sandwich)",
|
||||
"API 17: Android 4.2 (JellyBean)",
|
||||
"API 18: Android 4.3 (JellyBean)",
|
||||
"API 19: Android 4.4 (KitKat)",
|
||||
"API 20: Android 4.4W (KitKat Wear)",
|
||||
"API 21: Android 5.0 (Lollipop)",
|
||||
"API 22: Android 5.1 (Lollipop)",
|
||||
"API 23: Android 6.0 (Marshmallow)",
|
||||
"API 24: Android 7.0 (Nougat)",
|
||||
"API 25: Android 7.1 (Nougat)",
|
||||
"API 26: Android 8.0 (Oreo)",
|
||||
"API 27: Android 8.1 (Oreo)",
|
||||
"API 28: Android 9.0 (Pie)",
|
||||
"API 29: Android 10.0 (Q)",
|
||||
"API 30: Android 11.0 (R)",
|
||||
"API 31: Android 12.0 (S)",
|
||||
"API 32: Android 12.1L (S)",
|
||||
"API 33: Android 13.0 (Tiramisu)");
|
||||
}
|
||||
|
||||
private LinkedHashMap<String, String> getCppToolchans() {
|
||||
LinkedHashMap<String, String> cppStandartType = new LinkedHashMap<>();
|
||||
cppStandartType.put("Toolchain Default", "");
|
||||
cppStandartType.put("C++11", "-std=c++11");
|
||||
cppStandartType.put("C++14", "-std=c++14");
|
||||
cppStandartType.put("C++17", "-std=c++17");
|
||||
return cppStandartType;
|
||||
}
|
||||
|
||||
private void onNavigateBack() {
|
||||
if (!mLast) {
|
||||
getParentFragmentManager().popBackStack();
|
||||
} else {
|
||||
showTemplatesView();
|
||||
mLast = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void onNavigateNext() {
|
||||
if (!mLast) {
|
||||
showDetailsView();
|
||||
mLast = true;
|
||||
} else {
|
||||
createNewProject();
|
||||
}
|
||||
}
|
||||
|
||||
private void showTemplatesView() {
|
||||
|
||||
MaterialSharedAxis sharedAxis = new MaterialSharedAxis(MaterialSharedAxis.X, false);
|
||||
|
||||
TransitionManager.beginDelayedTransition((ViewGroup) requireView(), sharedAxis);
|
||||
binding.loadingLayout.getRoot().setVisibility(View.GONE);
|
||||
templatesBinding.getRoot().setVisibility(View.GONE);
|
||||
detailsBinding.getRoot().setVisibility(View.GONE);
|
||||
templatesBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
detailsBinding.tilToolchain.setVisibility(View.GONE);
|
||||
footerBinding.nextButton.setVisibility(View.GONE);
|
||||
footerBinding.nextButton.setText(string.next);
|
||||
footerBinding.exitButton.setText(string.exit);
|
||||
binding.wizardDescriptionId.setText(string.new_project);
|
||||
}
|
||||
|
||||
private void showDetailsView() {
|
||||
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
|
||||
|
||||
List<String> languages = new ArrayList<>();
|
||||
if (mCurrentTemplate != null) {
|
||||
if (mCurrentTemplate.isSupportJava()) {
|
||||
languages.add("Java");
|
||||
}
|
||||
if (mCurrentTemplate.isSupportKotlin()) {
|
||||
languages.add("Kotlin");
|
||||
}
|
||||
}
|
||||
|
||||
final var packageName =
|
||||
manager.getString(PREF_PACKAGE_DOMAIN_KEY, "com.example").concat(".myapplication");
|
||||
detailsBinding.etAppName.setText(string.template_def_app_name);
|
||||
detailsBinding.etPackageName.setText(packageName);
|
||||
detailsBinding.tilLanguage.setEnabled(languages.size() != 1);
|
||||
|
||||
detailsBinding.etLanguage.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
languages));
|
||||
|
||||
detailsBinding.etLanguage.setListSelection(0);
|
||||
|
||||
if (mCurrentTemplate.isCpp()) {
|
||||
detailsBinding.tilToolchain.setVisibility(View.VISIBLE);
|
||||
detailsBinding.etToolchain.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
getCppToolchans().keySet().toArray(new String[0])));
|
||||
|
||||
detailsBinding.etToolchain.setListSelection(0);
|
||||
detailsBinding.etToolchain.setText(getSelectedItem(0, detailsBinding.etToolchain), false);
|
||||
|
||||
showDialogNdkNotSupportedOfficially();
|
||||
}
|
||||
|
||||
detailsBinding.etLanguage.setText(getSelectedItem(0, detailsBinding.etLanguage), false);
|
||||
minSdkIndex = manager.getInt(PREF_MIN_SDK_INDEX_KEY, 5);
|
||||
|
||||
// google recommended use latest target sdk version
|
||||
targetSdkIndex = manager.getInt(PREF_TERGET_SDK_INDEX_KEY, getSdks().size() - 1);
|
||||
detailsBinding.etMinSdk.setListSelection(minSdkIndex);
|
||||
detailsBinding.etMinSdk.setText(getSelectedItem(minSdkIndex, detailsBinding.etMinSdk), false);
|
||||
|
||||
detailsBinding.etTargetSdk.setListSelection(targetSdkIndex);
|
||||
detailsBinding.etTargetSdk.setText(
|
||||
getSelectedItem(targetSdkIndex, detailsBinding.etTargetSdk), false);
|
||||
|
||||
setSaveLocation();
|
||||
|
||||
loadingLayout.getRoot().setVisibility(View.GONE);
|
||||
detailsBinding.getRoot().setVisibility(View.GONE);
|
||||
|
||||
MaterialSharedAxis sharedAxis = new MaterialSharedAxis(MaterialSharedAxis.X, true);
|
||||
|
||||
TransitionManager.beginDelayedTransition((ViewGroup) requireView(), sharedAxis);
|
||||
|
||||
detailsBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
templatesBinding.getRoot().setVisibility(View.GONE);
|
||||
binding.wizardDescriptionId.setText(mCurrentTemplate.getName());
|
||||
footerBinding.nextButton.setText(string.create_project);
|
||||
footerBinding.nextButton.setVisibility(View.VISIBLE);
|
||||
footerBinding.exitButton.setText(string.previous);
|
||||
}
|
||||
|
||||
private void initDetailsView() {
|
||||
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
|
||||
|
||||
detailsBinding
|
||||
.tilAppName
|
||||
.getEditText()
|
||||
.addTextChangedListener(
|
||||
new SingleTextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
verifyAppName(editable, true);
|
||||
}
|
||||
});
|
||||
|
||||
detailsBinding
|
||||
.tilPackageName
|
||||
.getEditText()
|
||||
.addTextChangedListener(
|
||||
new SingleTextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
verifyPackageName(editable);
|
||||
}
|
||||
});
|
||||
|
||||
detailsBinding.etMinSdk.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
getSdks()));
|
||||
|
||||
detailsBinding.etMinSdk.setOnItemClickListener(
|
||||
(parent, view, position, id) -> minSdkIndex = position);
|
||||
|
||||
detailsBinding.etTargetSdk.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
getSdks()));
|
||||
|
||||
detailsBinding.etTargetSdk.setOnItemClickListener(
|
||||
(parent, view, position, id) -> targetSdkIndex = position);
|
||||
|
||||
detailsBinding.tilSaveLocation.setEndIconOnClickListener(
|
||||
v -> {
|
||||
pickDirectory(
|
||||
p -> {
|
||||
manager.putString(PREF_SAVE_PROJECT_DIR_KEY, p.getAbsolutePath());
|
||||
Environment.setProjectDir(p);
|
||||
setSaveLocation();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void setPackageName(String appName) {
|
||||
final String packageName =
|
||||
Objects.requireNonNull(detailsBinding.etPackageName).getText().toString().trim();
|
||||
String newPackageName = AndroidUtils.appNameToPackageName(appName, packageName);
|
||||
detailsBinding.etPackageName.setText(newPackageName);
|
||||
}
|
||||
|
||||
private void setSaveLocation() {
|
||||
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
|
||||
|
||||
String saveProjectPath =
|
||||
manager.getString(PREF_SAVE_PROJECT_DIR_KEY, Environment.PROJECTS_DIR.getAbsolutePath())
|
||||
+ File.separator
|
||||
+ AndroidUtils.trimWhiteSpace(detailsBinding.etAppName.getText().toString().trim());
|
||||
|
||||
String newPath = FileUtil.getTargetNonExistPath(saveProjectPath, true);
|
||||
detailsBinding.etSaveLocation.setText(newPath);
|
||||
}
|
||||
|
||||
private void verifyPackageName(Editable editable) {
|
||||
String packageName = editable.toString();
|
||||
String pkgCheckerMsg = AndroidUtils.validatePackageName(packageName);
|
||||
if (!TextUtils.isEmpty(pkgCheckerMsg)) {
|
||||
detailsBinding.tilPackageName.setError(pkgCheckerMsg);
|
||||
} else {
|
||||
detailsBinding.tilPackageName.setErrorEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyAppName(Editable editable, boolean isAddToPackage) {
|
||||
String name = editable.toString().trim();
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
detailsBinding.tilAppName.setError(getString(string.wizard_error_name_empty));
|
||||
return;
|
||||
} else if (!AndroidUtils.validateNameChecker(AndroidUtils.trimWhiteSpace(name))) {
|
||||
detailsBinding.tilAppName.setError(getString(string.wizard_error_name_illegal));
|
||||
return;
|
||||
} else {
|
||||
detailsBinding.tilAppName.setErrorEnabled(false);
|
||||
}
|
||||
if (isAddToPackage) {
|
||||
setPackageName(name);
|
||||
}
|
||||
setSaveLocation();
|
||||
}
|
||||
|
||||
private void createProgressSheet() {
|
||||
mProgressSheet = new ProgressSheet();
|
||||
}
|
||||
|
||||
private void setMessage(String msg) {
|
||||
if (mProgressSheet == null) {
|
||||
createProgressSheet();
|
||||
}
|
||||
mProgressSheet.setMessage(msg);
|
||||
}
|
||||
|
||||
private void showDialogNdkNotSupportedOfficially() {
|
||||
DialogUtils.newMaterialDialogBuilder(requireContext())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(string.title_warning)
|
||||
.setMessage(string.msg_ndk_currently_unsupported)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
public interface OnProjectCreatedListener {
|
||||
void openProject(File project);
|
||||
}
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
package com.itsaky.androidide.viewmodel;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.blankj.utilcode.util.CollectionUtils;
|
||||
import com.itsaky.androidide.interfaces.ProjectWriterCallback;
|
||||
import com.itsaky.androidide.models.NewProjectDetails;
|
||||
import com.itsaky.androidide.models.ProjectTemplate;
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import com.itsaky.androidide.tasks.TaskExecutor;
|
||||
import com.itsaky.androidide.tasks.callables.ProjectCreatorCallable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class WizardViewModel extends AndroidViewModel {
|
||||
|
||||
private final MutableLiveData<List<ProjectTemplate>> mProjectTemplatesList =
|
||||
new MutableLiveData<>(CollectionUtils.newArrayList());
|
||||
private final MutableLiveData<Boolean> mLoadingState = new MutableLiveData<>(true);
|
||||
private final MutableLiveData<String> mErrorMessageState = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> mMessageState = new MutableLiveData<>();
|
||||
private final MutableLiveData<File> mCreatedProject = new MutableLiveData<>(null);
|
||||
|
||||
public WizardViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
}
|
||||
|
||||
public void createTemplatesList() {
|
||||
TaskExecutor.executeAsync(this::createTemplates);
|
||||
}
|
||||
|
||||
private Void createTemplates() {
|
||||
List<ProjectTemplate> mTemplates = new ArrayList<>();
|
||||
|
||||
ProjectTemplate
|
||||
empty =
|
||||
new ProjectTemplate()
|
||||
.setId(0)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_empty)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(), R.string.template_description_empty)
|
||||
.setImageId(R.drawable.template_empty_activity),
|
||||
basic =
|
||||
new ProjectTemplate()
|
||||
.setId(1)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_basic)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(), R.string.template_description_basic)
|
||||
.setImageId(R.drawable.template_basic_activity),
|
||||
drawer =
|
||||
new ProjectTemplate()
|
||||
.setId(2)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(), R.string.template_navigation_drawer)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_navigation_drawer)
|
||||
.setImageId(R.drawable.template_blank_activity_drawer),
|
||||
bottomTabs =
|
||||
new ProjectTemplate()
|
||||
.setId(3)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(), R.string.template_navigation_tabs)
|
||||
.setImageId(R.drawable.template_bottom_navigation_activity),
|
||||
tabs =
|
||||
new ProjectTemplate()
|
||||
.setId(4)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_tabs)
|
||||
.setImageId(R.drawable.template_blank_activity_tabs),
|
||||
fragmentViewModel =
|
||||
new ProjectTemplate()
|
||||
.setId(5)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_fragment_and_viewmodel)
|
||||
.setImageId(R.drawable.template_empty_activity),
|
||||
cppWizard =
|
||||
new ProjectTemplate()
|
||||
.setId(6)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setIsCpp(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_cpp)
|
||||
.setImageId(R.drawable.template_cpp_configure),
|
||||
compose =
|
||||
new ProjectTemplate()
|
||||
.setId(7)
|
||||
.setSupportKotlin(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_compose)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(), R.string.template_description_compose)
|
||||
.setImageId(R.drawable.template_compose_empty_activity),
|
||||
libgdx =
|
||||
new ProjectTemplate()
|
||||
.setId(8)
|
||||
.setSupportJava(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_libgdx)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(), R.string.template_description_libgdx)
|
||||
.setImageId(R.drawable.template_game_activity),
|
||||
noActivity =
|
||||
new ProjectTemplate()
|
||||
.setId(9)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_no_activity)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(), R.string.template_no_activity_description)
|
||||
.setImageId(R.drawable.template_no_activity),
|
||||
NoAndroidX =
|
||||
new ProjectTemplate()
|
||||
.setId(10)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(false)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_no_AndroidX)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(), R.string.template_description_noAndroidX)
|
||||
.setImageId(R.drawable.template_empty_noandroidx);
|
||||
|
||||
mTemplates.add(noActivity);
|
||||
mTemplates.add(empty);
|
||||
mTemplates.add(basic);
|
||||
mTemplates.add(drawer);
|
||||
mTemplates.add(bottomTabs);
|
||||
mTemplates.add(tabs);
|
||||
mTemplates.add(fragmentViewModel);
|
||||
mTemplates.add(cppWizard);
|
||||
mTemplates.add(compose);
|
||||
mTemplates.add(libgdx);
|
||||
mTemplates.add(NoAndroidX);
|
||||
|
||||
mProjectTemplatesList.postValue(mTemplates);
|
||||
mLoadingState.postValue(false);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public LiveData<List<ProjectTemplate>> getProjects() {
|
||||
return mProjectTemplatesList;
|
||||
}
|
||||
|
||||
public LiveData<Boolean> getLoadingState() {
|
||||
return mLoadingState;
|
||||
}
|
||||
|
||||
public LiveData<String> getErrorState() {
|
||||
return mErrorMessageState;
|
||||
}
|
||||
|
||||
public LiveData<File> getFileCreatedState() {
|
||||
return mCreatedProject;
|
||||
}
|
||||
|
||||
public LiveData<String> getStatusMessage() {
|
||||
return mMessageState;
|
||||
}
|
||||
|
||||
public void createProject(
|
||||
ProjectTemplate currentTemplate,
|
||||
String appName,
|
||||
String packageName,
|
||||
int minSdk,
|
||||
int targetSdk,
|
||||
String language,
|
||||
String cppFlags,
|
||||
String savePath) {
|
||||
final var details =
|
||||
new NewProjectDetails(
|
||||
appName, packageName, minSdk, targetSdk, language, cppFlags, savePath);
|
||||
final var callable = new ProjectCreatorCallable(currentTemplate, details, createCallback());
|
||||
TaskExecutor.executeAsync(callable);
|
||||
}
|
||||
|
||||
private ProjectWriterCallback createCallback() {
|
||||
return new ProjectWriterCallback() {
|
||||
|
||||
@Override
|
||||
public void beforeBegin() {
|
||||
mMessageState.setValue(getApplication().getString(R.string.msg_begin_project_write));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProcessTask(String taskName) {
|
||||
mMessageState.setValue(taskName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(File rootDir) {
|
||||
mCreatedProject.setValue(rootDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(String reason) {
|
||||
mErrorMessageState.setValue(reason);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/setup_wizard_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
tools:ignore="Overdraw">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/wizard_description_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="@string/new_project"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<include
|
||||
android:id="@+id/wizard_templates_layout"
|
||||
layout="@layout/wizard_templates"
|
||||
android:visibility="visible" />
|
||||
|
||||
<include
|
||||
android:id="@+id/wizard_details_layout"
|
||||
layout="@layout/wizard_details"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include
|
||||
android:id="@+id/loading_layout"
|
||||
layout="@layout/layout_loading_wizard"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<include
|
||||
android:id="@+id/footer_layout"
|
||||
layout="@layout/setup_footer" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,166 +0,0 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_app_name"
|
||||
style="@style/Widget.Material3.TextInputEditText.OutlinedBox.Dense"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/project_app_name"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="20"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:placeholderText="My Application"
|
||||
app:startIconDrawable="@drawable/ic_android">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_app_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_package_name"
|
||||
style="@style/Widget.Material3.TextInputEditText.OutlinedBox.Dense"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/package_name"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="40"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_app_name"
|
||||
app:placeholderText="com.example.myapplication"
|
||||
app:startIconDrawable="@drawable/ic_package">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_package_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_save_location"
|
||||
style="@style/Widget.Material3.TextInputEditText.OutlinedBox.Dense"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/wizard_save_location"
|
||||
app:endIconDrawable="@drawable/ic_folder"
|
||||
app:endIconMode="custom"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_package_name"
|
||||
app:placeholderText="/storage/emulated/0/AppProjects/MyApplication">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_save_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="start"
|
||||
android:inputType="textNoSuggestions" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_language"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:hint="@string/wizard_language"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_save_location">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/et_language"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_toolchain"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:hint="@string/wizard_toolchain"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_language">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/et_toolchain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_min_sdk"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:hint="@string/minimum_sdk"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_toolchain"
|
||||
app:startIconDrawable="@drawable/ic_min_sdk">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/et_min_sdk"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_target_sdk"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:hint="@string/target_sdk"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_min_sdk"
|
||||
app:startIconDrawable="@drawable/ic_target_sdk">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/et_target_sdk"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
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">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/template_recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
tools:itemCount="10"
|
||||
tools:listitem="@layout/layout_template_list_item"
|
||||
tools:spanCount="3" />
|
||||
|
||||
</FrameLayout>
|
||||
Reference in New Issue
Block a user