Форма в Android с вводом данных и возвратом результата

Учусь разработке под android. Задача - открыть из активити некую экранную форму, ввести данные (в разных местах приложения они разные - текст, число, дата) и вернуть обратно в вызывающую активити. Сейчас у меня в качестве диалоговой формы выступает несколько активити с разным набором полей для ввода. Мне кажется должны быть более изящные, визуально компактные, решения, чем целая новая активити с всего двумя полями для ввода и кнопкой. Если есть такие возможности, подскажите пож-та.


Ответы (1 шт):

Автор решения: Pavlo Khyzhniak

Оформи CustomDialog например так, для редактирования объекта, например Avto:

public class EditAutoDialogFragment extends DialogFragment {

    // Фрагменты не могут напрямую взаимодействовать между собой.
    // Для этого надо обращаться к контексту, в качестве которого
    // выступает класс Activity. Для обращения к activity, как правило,
    // создается вложенный интерфейс
    public interface OnFragmentEditAutoSendDataListener {
        void onSendData(int position,Auto item) throws ParseException;
        void onRemoveElement(int position) throws ParseException;
    } // OnFragmentSendDataListener

    // ссылка на активность, в которой будет запускаться диалог
    private OnFragmentEditAutoSendDataListener activityRetranslator;
    private Activity activity;
    Integer select;
    Auto item;

    // при подключении к активности, context -  ссылка на активнсоть
    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            activityRetranslator = (OnFragmentEditAutoSendDataListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context
                    + " должен реализовывать интерфейс OnFragmentSendDataListener");
        } // try-catch
    } // onAttach

    public EditAutoDialogFragment() {
        // Required empty public constructor
    }

    @NonNull
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // прочитать данные, переданные из активности (из точки вызова)
        // getArguments() - получить параметры из активности
        Bundle bundle = getArguments();

        // читаем строковый параметр
        this.select = bundle.getInt("select");
        this.item = bundle.getParcelable("item");

        activity = getActivity();

        AlertDialog.Builder builder = new AlertDialog.Builder(activity);

        builder
                .setTitle(getResources().getString(R.string.edit_auto))
                .setIcon(R.drawable.edit)  // иконка из ресурсов нашего приложения
                .setView(R.layout.homework010_fragment_edit_auto_dialog)       // добавить разметку - работает только с API21 и старше
//                .setPositiveButton("ОК", onClickListener)   // для кнопок можно установить текст и обработчик
        // нажатия.
        // для кнопки "Отмена" обработчик установлен
//                .setNegativeButton("Отмена", onClickListener)
        ;

        return builder.create();
    } // onCreateDialog


    EditText edtBrandName, edtModelName, edtYearOfManufacture, edtEnginePower, edtPrice, edtSymbolicImage;
    Button btnSave, btnDelete, btnCancel;

    Dialog dialog;

    @Override
    public void onStart() {
        super.onStart();
        // возможна работа с элементами разметки диалога
        // при помощи getDialog().findBiewById()
        setViews();

    }

    @SuppressLint("SetTextI18n")
    private void setViews() {
        // получить ссылки на элементы интерфейса

        dialog = getDialog();

        edtBrandName = (EditText) dialog.findViewById(R.id.edtBrandName);
        edtModelName = (EditText) dialog.findViewById(R.id.edtModelName);
        edtYearOfManufacture = (EditText) dialog.findViewById(R.id.edtYearOfManufacture);
        edtEnginePower = (EditText) dialog.findViewById(R.id.edtEnginePower);
        edtPrice = (EditText) dialog.findViewById(R.id.edtPrice);
        edtSymbolicImage = (EditText) dialog.findViewById(R.id.edtSymbolicImage);

        btnSave = (Button) dialog.findViewById(R.id.btnSave);
        btnDelete = (Button) dialog.findViewById(R.id.btnDelete);
        btnCancel = (Button) dialog.findViewById(R.id.btnCancel);

        edtBrandName.setText(this.item.getBrandName());
        edtModelName.setText(this.item.getModelName());
        edtYearOfManufacture.setText(String.format(Locale.UK, "%d", item.getYearOfManufacture()));
        edtEnginePower.setText(String.format(Locale.UK, "%.2f", item.getEnginePower()));
        edtPrice.setText(String.format(Locale.UK, "%d", item.getPrice()));
//        edtYearOfManufacture.setText(Integer.toString(this.item.getYearOfManufacture()));
//        edtEnginePower.setText(Double.toString(this.item.getEnginePower()));
//        edtPrice.setText(Integer.toString(this.item.getPrice()));
        edtSymbolicImage.setText(this.item.getSymbolicImage());

        btnCancel.setOnClickListener(this::onButtonClickListener);
        btnDelete.setOnClickListener(this::onButtonClickListener);
        btnSave.setOnClickListener(this::onButtonClickListener);
    }

    @SuppressLint("NonConstantResourceId")
    private void onButtonClickListener(View v) {
        switch (v.getId()) {
            case R.id.btnSave:
                try {
                    refreshItem();
                    activityRetranslator.onSendData(this.select,this.item);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if (dialog != null) {
                    if (dialog.isShowing()) {
                        dialog.dismiss();
                        dialog = null;
                    }
                }
                break;
            case R.id.btnDelete:
                try {
                    activityRetranslator.onRemoveElement(this.select);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            case R.id.btnCancel:
                if (dialog != null) {
                    if (dialog.isShowing()) {
                        dialog.dismiss();
                        dialog = null;
                    }
                }
                break;
        }
    }

    private void refreshItem() throws ParseException {
        this.item.setBrandName(edtBrandName.getText().toString());
        this.item.setModelName(edtModelName.getText().toString());
        this.item.setYearOfManufacture(Integer.parseInt(edtYearOfManufacture.getText().toString()));
        this.item.setEnginePower(Double.parseDouble(edtEnginePower.getText().toString()));
        this.item.setPrice(Integer.parseInt(edtPrice.getText().toString()));
        this.item.setSymbolicImage(edtSymbolicImage.getText().toString());

    }

    //    String parameter;
    // onClick
    // Слушатель события клик по кнопке диалога
    DialogInterface.OnClickListener onClickListener = (dialogInterface, id) -> {
        // определить состояние чек-бокса
//        Dialog thisDialog = getDialog();   // ссылка на разметку
//
//        // определить набранный в строке ввода текст
//        EditText editText = thisDialog.findViewById(R.id.editText);
//
//        parameter = editText.getText().toString();

        switch (id) {
            case Dialog.BUTTON_POSITIVE:

                // подготовить и показть Toast
                // getBaseContext() - ссылка на активность, в которой создан диалог
                Toast toast = Toast.makeText(activity.getBaseContext(), "", Toast.LENGTH_LONG);
                toast.setText("Запрос выполнен");
                toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
                toast.show();
                break;
            case Dialog.BUTTON_NEGATIVE:
        } // switch

    };
}

И разметка

<?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:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".homework010.fragments.EditAutoDialogFragment">


        <GridLayout
            android:layout_height="match_parent"
            android:layout_width="wrap_content">

            <TextView
                android:id="@+id/txvBrandName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="0"
                android:layout_column="0"
                android:text="@string/Brand" />

            <TextView
                android:id="@+id/txvModelName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="1"
                android:layout_column="0"
                android:text="@string/Model" />

            <TextView
                android:id="@+id/txvYearOfManufacture"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="2"
                android:layout_column="0"
                android:text="@string/YearOfManufacture" />

            <TextView
                android:id="@+id/txvEnginePower"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="3"
                android:layout_column="0"
                android:text="@string/EnginePower" />

            <TextView
                android:id="@+id/txvPrice"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="4"
                android:layout_column="0"
                android:text="@string/Price" />

            <TextView
                android:id="@+id/txvSymbolicImage"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="5"
                android:layout_column="0"
                android:text="@string/SymbolicImage" />


            <EditText
                android:id="@+id/edtBrandName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="0"
                android:layout_column="1"
                android:autofillHints="@string/hint_lastname"
                android:inputType="text"
                android:labelFor="@id/txvLastName"
                android:maxWidth="400dp"
                android:minWidth="100dp" />

            <EditText
                android:id="@+id/edtModelName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="1"
                android:layout_column="1"
                android:autofillHints="@string/hint_firstname"
                android:inputType="text"
                android:labelFor="@id/txvFirstName"
                android:maxWidth="400dp"
                android:minWidth="100dp" />

            <EditText
                android:id="@+id/edtYearOfManufacture"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="2"
                android:layout_column="1"
                android:autofillHints="@string/hint_flightnumber"
                android:inputType="numberDecimal"
                android:labelFor="@id/txvFlightNumber"
                android:maxWidth="400dp"
                android:minWidth="100dp" />

            <EditText
                android:id="@+id/edtEnginePower"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="3"
                android:layout_column="1"
                android:autofillHints="@string/hint_departuredate"
                android:inputType="date"
                android:labelFor="@id/txvDepartureDate"
                android:maxWidth="400dp"
                android:minWidth="100dp" />

            <EditText
                android:id="@+id/edtPrice"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="4"
                android:layout_column="1"
                android:autofillHints="@string/hint_destination"
                android:inputType="date"
                android:labelFor="@id/txvDestination"
                android:maxWidth="400dp"
                android:minWidth="100dp" />

            <EditText
                android:id="@+id/edtSymbolicImage"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_row="5"
                android:layout_column="1"
                android:autofillHints="@string/hint_destination"
                android:inputType="date"
                android:labelFor="@id/txvDestination"
                android:maxWidth="400dp"
                android:minWidth="100dp" />

        </GridLayout>

    <LinearLayout
        android:gravity="center"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnSave"
            android:text="@string/btn_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btnDelete"
            android:text="@string/btn_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btnCancel"
            android:text="@string/btn_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

Сам объект:

public class Auto implements Parcelable {
    String brandName;//бренд
    String modelName;//модель
    int yearOfManufacture;//год выпуска
    double enginePower;//мощность двигателя
    int price;//цена
    String symbolicImage;//условное изображение

    protected Auto(Parcel in) {
        brandName = in.readString();
        modelName = in.readString();
        yearOfManufacture = in.readInt();
        enginePower = in.readDouble();
        price = in.readInt();
        symbolicImage = in.readString();
    }

    public static final Creator<Auto> CREATOR = new Creator<Auto>() {
        @Override
        public Auto createFromParcel(Parcel in) {
            return new Auto(in);
        }

        @Override
        public Auto[] newArray(int size) {
            return new Auto[size];
        }
    };

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        if (brandName.length() > 0)
            this.brandName = brandName;
    }

    public String getModelName() {
        return modelName;
    }

    public void setModelName(String modelName) {
        if (modelName.length() > 0)
            this.modelName = modelName;
    }

    public int getYearOfManufacture() {
        return yearOfManufacture;
    }

    public void setYearOfManufacture(int yearOfManufacture) {
        if (yearOfManufacture > 0)
            this.yearOfManufacture = yearOfManufacture;
    }

    public double getEnginePower() {
        return enginePower;
    }

    public void setEnginePower(double enginePower) {
        if (enginePower > 0)
            this.enginePower = enginePower;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        if (price > 0)
            this.price = price;
    }

    public String getSymbolicImage() {
        return symbolicImage;
    }

    public void setSymbolicImage(String symbolicImage) {
        if (symbolicImage.length() > 0)
            this.symbolicImage = symbolicImage;
    }


    public Auto(
            String _brandName,
            String _modelName,
            int _yearOfManufacture,
            double _enginePower,
            int _price,
            String _symbolicImage
    ) {
        this.brandName = _brandName;
        this.modelName = _modelName;
        this.yearOfManufacture = _yearOfManufacture;
        this.enginePower = _enginePower;
        this.price = _price;
        this.symbolicImage = _symbolicImage;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(brandName);
        dest.writeString(modelName);
        dest.writeInt(yearOfManufacture);
        dest.writeDouble(enginePower);
        dest.writeInt(price);
        dest.writeString(symbolicImage);
    }
}

И используй где надо:

private void dialogEdit(int position) {
        // ссылка на элемент коллекции
        Auto item = itemsList.get(position);

        if (item != null) {

            // создать диалог, передать ему строку - элемент списка
            EditAutoDialogFragment dialog = new EditAutoDialogFragment();

            // передача параметров в диалог - через Bundle
            Bundle args = new Bundle();    // объект для передачи параметров в диалог

            args.putInt("select", position);
            args.putParcelable("item", item);

            // метод базового класса DialogFragment
            dialog.setArguments(args);

            // отображение диалогового окна
            dialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "dialogEditAuto");
        }
    }
→ Ссылка