目标是创建一个Android密码输入页面,包含数字、大写字母、小写字母和特殊符号四个部分,同时支持上下滑动和左右滑动切换不同部分。
1.首先,在布局文件(activity_main.xml)中添加ViewPager和TabLayout:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:tabIndicatorColor="@android:color/white" app:tabMode="scrollable" /> </RelativeLayout>
2.在Activity【或Fragment】中,设置ViewPager和TabLayout,并创建PagerAdapter用于管理不同部分的页面:
package com.example.password; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import androidx.viewpager.widget.ViewPager; import android.os.Bundle; import com.google.android.material.tabs.TabLayout; public class MainActivity extends AppCompatActivity { private ViewPager viewPager; private TabLayout tabLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = findViewById(R.id.viewPager); tabLayout = findViewById(R.id.tabLayout); // Create an adapter that returns a fragment for each of the four sections viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager())); // Connect the ViewPager with TabLayout tabLayout.setupWithViewPager(viewPager); // Set tab titles tabLayout.getTabAt(0).setText("数字"); tabLayout.getTabAt(1).setText("大写字母"); tabLayout.getTabAt(2).setText("小写字母"); tabLayout.getTabAt(3).setText("特殊符号"); } // FragmentPagerAdapter for managing fragments for each section private class SectionsPagerAdapter extends FragmentPagerAdapter { public SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { switch (position) { case 0: return new DigitFragment(); case 1: return new UppercaseLetterFragment(); case 2: return new LowercaseLetterFragment(); case 3: return new SpecialCharacterFragment(); default: return null; } } @Override public int getCount() { return 4; // Total number of sections } } }
3.创建每个部分的Fragment:DigitFragment、UppercaseLetterFragment、LowercaseLetterFragment和SpecialCharacterFragment。这些Fragment分别显示数字、大写字母、小写字母和特殊字符。每个Fragment都会简单地显示一个RecyclerView,用于显示对应的密码字符或者按钮。
package com.example.password; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class DigitFragment extends Fragment { private RecyclerView recyclerView; private PasswordAdapter adapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_password, container, false); recyclerView = rootView.findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3)); // Grid layout with 3 columns adapter = new PasswordAdapter(generateDigitList()); recyclerView.setAdapter(adapter); return rootView; } private List<String> generateDigitList() { List<String> digits = new ArrayList<>(); for (int i = 0; i <= 9; i++) { digits.add(String.valueOf(i)); } return digits; } }
package com.example.password; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class UppercaseLetterFragment extends Fragment { private RecyclerView recyclerView; private PasswordAdapter adapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_password, container, false); recyclerView = rootView.findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3)); // Grid layout with 3 columns adapter = new PasswordAdapter(generateUppercaseList()); recyclerView.setAdapter(adapter); return rootView; } private List<String> generateUppercaseList() { List<String> uppercaseLetters = new ArrayList<>(); for (char c = 'A'; c <= 'Z'; c++) { uppercaseLetters.add(String.valueOf(c)); } return uppercaseLetters; } }
package com.example.password; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class LowercaseLetterFragment extends Fragment { private RecyclerView recyclerView; private PasswordAdapter adapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_password, container, false); recyclerView = rootView.findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3)); // Grid layout with 3 columns adapter = new PasswordAdapter(generateLowercaseList()); recyclerView.setAdapter(adapter); return rootView; } private List<String> generateLowercaseList() { List<String> lowercaseLetters = new ArrayList<>(); for (char c = 'a'; c <= 'z'; c++) { lowercaseLetters.add(String.valueOf(c)); } return lowercaseLetters; } }
package com.example.password; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class SpecialCharacterFragment extends Fragment { private RecyclerView recyclerView; private PasswordAdapter adapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_password, container, false); recyclerView = rootView.findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3)); // Grid layout with 3 columns adapter = new PasswordAdapter(generateSpecialCharacterList()); recyclerView.setAdapter(adapter); return rootView; } private List<String> generateSpecialCharacterList() { List<String> specialCharacters = new ArrayList<>(); // Add commonly used special characters here, adjust as per your requirements specialCharacters.add("!"); specialCharacters.add("@"); specialCharacters.add("#"); specialCharacters.add("$"); specialCharacters.add("%"); specialCharacters.add("&"); specialCharacters.add("*"); specialCharacters.add("-"); specialCharacters.add("+"); specialCharacters.add("="); return specialCharacters; } }
4.共用的 RecyclerView 适配器 PasswordAdapter.java
package com.example.password; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.List; public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.PasswordViewHolder> { private List<String> dataList; public PasswordAdapter(List<String> dataList) { this.dataList = dataList; } @NonNull @Override public PasswordViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_password, parent, false); return new PasswordViewHolder(view); } @Override public void onBindViewHolder(@NonNull PasswordViewHolder holder, int position) { String item = dataList.get(position); holder.textView.setText(item); } @Override public int getItemCount() { return dataList.size(); } static class PasswordViewHolder extends RecyclerView.ViewHolder { TextView textView; PasswordViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.text_view_item); } } }
5.每个Fragment中,根据需要创建布局和逻辑来显示对应的密码字符。
布局文件 fragment_password.xml
该布局文件用于每个Fragment中RecyclerView的布局:
<?xml version="1.0" encoding="utf-8"?> <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp" android:clipToPadding="false" android:scrollbars="vertical" />
布局文件 item_password.xml
该布局文件用于RecyclerView中每个项的布局:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text_view_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="16dp" android:textSize="18sp" android:background="?attr/selectableItemBackground" android:textColor="@android:color/black" android:gravity="center" android:textAppearance="?android:attr/textAppearanceListItem" />
现在展示出的页面如下
那如果我们需要再给tab行下面加一个输入框【要在每个标签下方添加一个输入框】 ,并添加回退、清理和确定按钮。
也就是说:每个标签页(Tab)上方有一个显示密码规则的区域(例如数字、大写字母、小写字母、特殊字符),下方是一个固定的输入框和三个按钮(回退、清理、确定),切换标签页时,下方的输入框和按钮保持不变,只是上方的密码规则区域内容变化。
这样我们可以采用TabLayout
和 ViewPager
的组合来实现,每个标签页对应一个 Fragment
,下方的输入框和按钮放在一个单独的布局中,使其在切换标签页时保持不变。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:elevation="6dp" android:minHeight="?attr/actionBarSize" android:theme="@style/ThemeOverlay.MaterialComponents.ActionBar" /> <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tab_layout" /> <LinearLayout android:id="@+id/password_controls_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentBottom="true" android:padding="16dp"> <EditText android:id="@+id/edit_text_password" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:hint="Enter password" android:inputType="textPassword" /> <Button android:id="@+id/button_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Back" /> <Button android:id="@+id/button_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" /> <Button android:id="@+id/button_confirm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Confirm" /> </LinearLayout> </RelativeLayout>
2.修改MainActivity.java
import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import androidx.viewpager.widget.ViewPager; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.google.android.material.tabs.TabLayout; public class MainActivity extends AppCompatActivity { private EditText editTextPassword; private Button buttonBack, buttonClear, buttonConfirm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editTextPassword = findViewById(R.id.edit_text_password); buttonBack = findViewById(R.id.button_back); buttonClear = findViewById(R.id.button_clear); buttonConfirm = findViewById(R.id.button_confirm); ViewPager viewPager = findViewById(R.id.view_pager); TabLayout tabLayout = findViewById(R.id.tab_layout); // Set up ViewPager with adapter PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(pagerAdapter); tabLayout.setupWithViewPager(viewPager); buttonBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!editTextPassword.getText().toString().isEmpty()) { String currentText = editTextPassword.getText().toString(); editTextPassword.setText(currentText.substring(0, currentText.length() - 1)); } } }); buttonClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { editTextPassword.setText(""); } }); buttonConfirm.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String password = editTextPassword.getText().toString(); // Example: validatePassword(password); Toast.makeText(MainActivity.this, "Password entered: " + password, Toast.LENGTH_SHORT).show(); } }); } private class PagerAdapter extends FragmentPagerAdapter { private final String[] tabTitles = new String[]{"Digits", "Uppercase", "Lowercase", "Special"}; public PagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { switch (position) { case 0: return new DigitFragment(); case 1: return new UppercaseLetterFragment(); case 2: return new LowercaseLetterFragment(); case 3: return new SpecialCharacterFragment(); default: return null; } } @Override public int getCount() { return tabTitles.length; } @Override public CharSequence getPageTitle(int position) { return tabTitles[position]; } } }
3.更新 Fragment 类
更新每个标签页的 Fragment 类【DigitFragment
、UppercaseLetterFragment
、LowercaseLetterFragment
、SpecialCharacterFragment
】,使用新的布局文件,并在 Fragment 中查找并设置输入框和按钮的点击事件。
在实现左右滑动的同时,如果需要支持上下滑动,可以采用每个tab页的内容使用了ListView来实现垂直滚动,而整体的tab切换使用了TabBar和TabBarView来管理
标签:androidx,ViewPager,new,滑动,import,android,public,TabLayout,View From: https://www.cnblogs.com/yddbkdz/p/18321999