You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Firebase认证手机号OTP登录:SignUpActivity中实现OTP输入Fragment弹窗

Replace OTP Activity with a Modal Fragment Popup in SignUpActivity

Hey there! I get you—replacing a separate Activity with a popup Fragment feels way more seamless for OTP verification. Let’s break down exactly how to pull this off:

1. Create an OTP Dialog Fragment

First, we’ll build a DialogFragment that acts as your modal OTP popup. This gives us the centered, overlay behavior we want.

Step 1.1: Define the Fragment Layout (fragment_otp_verification.xml)

Make a layout with your OTP input fields, verification button, and cancel option. Here’s a basic example:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="24dp"
    android:background="@drawable/rounded_dialog_bg">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Enter OTP"
        android:textSize="20sp"
        android:textStyle="bold"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="We’ve sent a code to your phone number"
        android:textSize="14sp"
        android:layout_marginTop="8dp"/>

    <!-- Use a custom OTP input view or single EditText for digits -->
    <EditText
        android:id="@+id/et_otp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="XXXXXX"
        android:inputType="number"
        android:maxLength="6"
        android:layout_marginTop="16dp"/>

    <Button
        android:id="@+id/btn_verify_otp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Verify"
        android:background="@color/colorPrimary"
        android:textColor="@android:color/white"
        android:layout_marginTop="16dp"/>

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Cancel"
        android:background="@android:color/transparent"
        android:textColor="@color/colorPrimary"
        android:layout_marginTop="8dp"/>

</LinearLayout>

Step 1.2: Implement the Dialog Fragment Class (OtpVerificationFragment.java)

Set up the fragment as a dialog, handle user input, and add a callback to communicate with SignUpActivity:

public class OtpVerificationFragment extends DialogFragment {

    private OnOtpInteractionListener mListener;
    private EditText etOtp;

    // Interface to pass events back to the Activity
    public interface OnOtpInteractionListener {
        void onOtpVerified(String otp);
        void onOtpCanceled();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Configure dialog style to remove default title and enable floating behavior
        setStyle(DialogFragment.STYLE_NORMAL, R.style.OtpDialogStyle);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_otp_verification, container, false);
        
        etOtp = view.findViewById(R.id.et_otp);
        Button btnVerify = view.findViewById(R.id.btn_verify_otp);
        Button btnCancel = view.findViewById(R.id.btn_cancel);

        // Handle verify button click
        btnVerify.setOnClickListener(v -> {
            String otp = etOtp.getText().toString().trim();
            if (!otp.isEmpty() && otp.length() == 6) {
                if (mListener != null) {
                    mListener.onOtpVerified(otp);
                    dismiss();
                }
            } else {
                Toast.makeText(getContext(), "Please enter a valid 6-digit OTP", Toast.LENGTH_SHORT).show();
            }
        });

        // Handle cancel button click
        btnCancel.setOnClickListener(v -> {
            if (mListener != null) {
                mListener.onOtpCanceled();
            }
            dismiss();
        });

        // Add your existing auto-fill logic here
        setupOtpAutoFill();

        return view;
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        // Attach the Activity as the listener
        try {
            mListener = (OnOtpInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement OnOtpInteractionListener");
        }
    }

    private void setupOtpAutoFill() {
        // Copy your existing auto-fill code here (e.g., SMS Retriever API, broadcast receiver)
        // Example placeholder:
        // SmsRetrieverClient client = SmsRetriever.getClient(requireContext());
        // Task<Void> task = client.startSmsRetriever();
        // ... rest of your auto-fill implementation
    }

    // Adjust dialog size and position when it loads
    @Override
    public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            Window window = dialog.getWindow();
            if (window != null) {
                window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                window.setGravity(Gravity.CENTER);
            }
        }
    }
}

Step 1.3: Define Dialog Style (styles.xml)

Add a style to make the dialog look clean:

<style name="OtpDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowIsFloating">true</item>
</style>

2. Trigger the Fragment from SignUpActivity

Instead of launching a new Intent after phone number submission, show the OTP fragment:

// Inside SignUpActivity, after validating the phone number
Button btnSubmitPhone = findViewById(R.id.btn_submit_phone);
btnSubmitPhone.setOnClickListener(v -> {
    String phoneNumber = etPhone.getText().toString().trim();
    if (!phoneNumber.isEmpty()) {
        // Send OTP to the user's phone (your existing logic)
        
        // Show the OTP popup
        OtpVerificationFragment otpFragment = new OtpVerificationFragment();
        otpFragment.show(getSupportFragmentManager(), "OTP_VERIFICATION_DIALOG");
    } else {
        Toast.makeText(this, "Please enter a valid phone number", Toast.LENGTH_SHORT).show();
    }
});

3. Implement the Listener in SignUpActivity

Make SignUpActivity implement the OnOtpInteractionListener to handle verification results:

public class SignUpActivity extends AppCompatActivity implements OtpVerificationFragment.OnOtpInteractionListener {

    // ... your existing SignUpActivity code

    @Override
    public void onOtpVerified(String otp) {
        // Handle successful OTP verification here
        // e.g., call your API to validate the OTP, then proceed with sign-up
        Toast.makeText(this, "OTP Verified: " + otp, Toast.LENGTH_SHORT).show();
        // Continue your sign-up flow
    }

    @Override
    public void onOtpCanceled() {
        // Handle cancel action (e.g., reset to phone input step)
        Toast.makeText(this, "OTP verification canceled", Toast.LENGTH_SHORT).show();
    }
}

4. Optional: Migrate Auto-Fill Logic

If you had auto-fill working in your old OTP Activity, just move that code into the setupOtpAutoFill() method in the fragment. The logic (like SMS Retriever API integration) works exactly the same way here.

That’s all! This setup gives you a smooth, in-place OTP verification popup instead of switching between activities.

内容的提问来源于stack exchange,提问作者Rohan verma

火山引擎 最新活动