【问题标题】:How to get text from an EditText in a ViewPager2?如何从 ViewPager2 中的 EditText 获取文本?
【发布时间】:2021-04-18 12:41:32
【问题描述】:

我有一个 ViewPager2,有两页。一个是获取电子邮件,另一个是获取电话号码。为了获得值,我向适配器添加了两个 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 中的值。

【问题讨论】:

    标签: android android-fragments android-viewpager2


    【解决方案1】:

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

    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 类,它保存 LiveData 对象中的 EditText 字段的值。然后从活动(或片段)中观察这些字段。请看下面的代码:

    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 类来连接 viewPager 片段和它们的宿主活动(或其他片段,视情况而定)。 当用户使用 TextWatcher 键入时,我从 EditText 获取文本。

    【讨论】:

    • 如何从片段中获取editText的值到父级?
    • 您可以为此使用接口。我需要有关您希望它如何工作的更多详细信息,以便我可以更新我的答案。在您的片段中单击按钮后,您是否获得了价值?
    • 是的,我想在单击按钮后获取值,该按钮是活动的一部分,而不是片段
    • 在这种情况下我将如何使用接口?
    • 我发现使用接口是行不通的,我使用了不同的方法。我已经更新了我的答案@MárioFernandes
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      更好的方法是使用 SharedViewModel。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-25
        • 1970-01-01
        • 1970-01-01
        • 2014-07-12
        • 2019-04-09
        • 1970-01-01
        相关资源
        最近更新 更多