如何从 ViewPager2 中的 EditText 获取文本?

How to get text from an EditText in a ViewPager2?

我有一个 ViewPager2,有两个页面。一个收到电子邮件,另一个收到 phone 号码。为了获取这些值,我向适配器添加了两个 get 方法,但我不确定这是正确且最安全的方法。这是我的代码:

  public class PhoneEmailFragment extends Fragment {

private View view;
private final String[] tabs = {"Phone", "Email"};
private User user;
private int pageSelected = 0;


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_phone_email, container, false);

    return view;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    assert getArguments() != null;
    user = getArguments().getParcelable("user");
}

@Override
public void onStart() {
    super.onStart();
    viewpagerSetup();
}

private void viewpagerSetup() {

    TabLayout tabLayout = view.findViewById(R.id.register_phone_email_tab);
    ViewPager2 viewPager2 = view.findViewById(R.id.register_viewpager);

    SwipeAdapter adapter = new SwipeAdapter(this);
    viewPager2.setAdapter(adapter);

    viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            pageSelected = position;
        }
    });

    new TabLayoutMediator(
            tabLayout,
            viewPager2,
            (tab, position) -> tab.setText(tabs[position])
    ).attach();

}

public void saveValue() {
        switch (pageSelected) {
            case 0:
                user.setUserPhoneNumber();
                break;
            case 1:
                user.setUserEmail();
                break;
        }

}

static class SwipeAdapter extends FragmentStateAdapter {

    public SwipeAdapter(@NonNull Fragment fragment) {
        super(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {

        Fragment fragment = new Fragment();

        switch (position) {
            case 0:
                fragment = new PhoneFieldFragment();
                break;
            case 1:
                fragment = new EmailFieldFragment();
                break;
        }
        return fragment;
    }

    @Override
    public int getItemCount() {
        return 2;
    }

}

}

我想在 saveValue() 方法中使用来自 EditText 的值。

在您的 Fragment 代码中进行此操作。它会很干净并且易于维护。

获取 EditText 的值应该在您的片段 classes 中完成。为了从片段中获取 EditText 的值,应从 SwipeAdapter class 中删除 2 个 get 方法,并且应将 findViewById() 调用放在片段中 class如下所示:

public class EmailFieldFragment extends Fragment {

    private MainViewModel mainViewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_email_field, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Do this after an action, example - after a button click
        EditText emailEt = view.findViewById(R.id.email_et);
        emailEt.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
               if (count < 1) { // i.e - no user input
                    mainViewModel.setEmail("");
                } else {
                    mainViewModel.setEmail(s.toString());
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }
}

我更新了 SwipeAdapter 接受片段列表如下:

public class SwipeAdapter extends FragmentStateAdapter {

    private final List<Fragment> fragments;

    public SwipeAdapter(@NonNull FragmentActivity fragmentActivity, 
    List<Fragment> fragmentList) {
        super(fragmentActivity);
        this.fragments = fragmentList;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return fragments.get(position);
    }

    @Override
    public int getItemCount() {
        return fragments.size();
    }
}

我创建了一个 viewModel class,它保存 LiveData 对象中 EditText 字段的值。然后从 activity (或片段)观察这些字段。请看下面的代码:

public class MainViewModel extends ViewModel {
    private final MutableLiveData<String> _email = new 
    MutableLiveData<>();
    public LiveData<String> email = _email;

    private final MutableLiveData<String> _phone = new 
    MutableLiveData<>();
    public LiveData<String> phone = _phone;

    public void setEmail(String email) {
        _email.setValue(email);
    }

    public void setPhone(String phone) {
        _phone.setValue(phone);
    }
}

我还添加了生命周期依赖项。

最后,这是下面 Activity 的代码:

public class MainActivity extends AppCompatActivity {

private String email = "";
private String phone = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    MainViewModel mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);

    PhoneFieldFragment phoneFieldFragment = new PhoneFieldFragment();
    EmailFieldFragment emailFieldFragment = new EmailFieldFragment();
    List<Fragment> fragmentList = new ArrayList<>();
    fragmentList.add(phoneFieldFragment);
    fragmentList.add(emailFieldFragment);
    SwipeAdapter swipeAdapter = new SwipeAdapter(this, fragmentList);
    ViewPager2 viewPager = findViewById(R.id.viewPager);
    viewPager.setAdapter(swipeAdapter);

    Button button = findViewById(R.id.get_field_button);

    mainViewModel.email.observe(MainActivity.this, new Observer<String>() {
        @Override
        public void onChanged(String s) {
            email = s;
        }
    });

    mainViewModel.phone.observe(MainActivity.this, new Observer<String>() {
        @Override
        public void onChanged(String s) {
            phone = s;
        }
    });

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this, "Email: " + email + "\nPhone: " + phone, Toast.LENGTH_SHORT).show();
            // Both email and phone number are available here, so you can call your setValue() method here
        }
    });
  }
}

This is a link to the entire codebase on github

编辑

我使用了一个共享的 viewModel class 来连接 viewPager 片段和它们的宿主 activity(或者另一个片段,视情况而定)。 当用户使用 TextWatcher.

输入时,我从 EditText 获取文本

更好的方法是使用 SharedViewModel。