androidx.viewpager2.widget.ViewPager2
以滑动的方式显示view或fragment,ViewPager2通过Adapter显示Views或Fragments。
Adapter类继承FragmentStateAdapter,感知各个页面的变化。
//activity
val vp2 = findViewById<View>(R.id.vp2) as ViewPager2
val fragments = mutableListOf(Fragment1(), Fragment2())
val adapter = MyAdapter(this, fragments as ArrayList<Fragment>)
vp2.adapter = adapter
vp2.orientation = ViewPager2.ORIENTATION_VERTICAL//设置滑动方式为垂直方向
//Adapter
class MyAdapter(fragmentActivity: FragmentActivity, private val fragments: ArrayList<Fragment>) : FragmentStateAdapter(fragmentActivity) {
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
override fun getItemCount():Int {
return fragments.size
}
}
//Fragment
class Fragment1 : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val tv = TextView(context)
tv.text = "第一页"
tv.setBackgroundColor(Color.parseColor("#f7acbc"))
tv.gravity = Gravity.CENTER
return tv
}
}
class Fragment2 : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val tv = TextView(context)
tv.text = "第二页"
tv.setBackgroundColor(Color.parseColor("#11a2bc"))
tv.gravity = Gravity.CENTER
return tv
}
}
//build.gradle
implementation "androidx.viewpager2:viewpager2:1.0.0"
androidx.recyclerview.widget.RecyclerView
RecylerView可通过Adapter和ViewHolder进行显示,类似于表格显示。
Adapter和ViewHolder类都需要继承RecylerView.Adapter和RecylerView.ViewHolder
//activity
val listData = mutableListOf<TestData>(
TestData("北京市"),
TestData("上海市"),
TestData("广州市"),
TestData("深圳市"),
TestData("杭州市"),
TestData("南京市"),
TestData("成都市"),
TestData("重庆市"),
TestData("西安市"),
TestData("天津市"),
TestData("苏州市"),
)
var listTestData = TestAdapter {
Log.d("选择的项:","$it")//最后响应
}.apply {
data = listData
}
binding.recylerView.layoutManager = LinearLayoutManager(this)
binding.recylerView.adapter = listTestData
//adapter
class TestAdapter(private var adapterListener: (testData: TestData) -> Unit) :
RecyclerView.Adapter<TestViewHolder>() {
var data = mutableListOf<TestData>()
set(value) {
if (value.isNotEmpty()) {
field.addAll(value)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestViewHolder {
val binding = ViewFormBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return TestViewHolder(binding)
}
override fun getItemCount(): Int {
return data.size
}
override fun onBindViewHolder(holder: TestViewHolder, position: Int) {
holder.bind(data[position]) {
data.forEach {
it.isSelected = false
}
data[position].isSelected = true
notifyDataSetChanged()
adapterListener.invoke(data[position])//其次响应
}
}
}
//viewHodler
class TestViewHolder(private val binding: ViewFormBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(testData: TestData, ViewListener: (testData: TestData) -> Unit) {
binding.contentTv.text = testData.name
var color = if (testData.isSelected) {
Color.parseColor("#495CCE")
} else {
Color.parseColor("#666666")
}
binding.contentTv.setTextColor(color)
itemView.setOnClickListener {//首先响应
ViewListener.invoke(testData)
}
}
}
//data
data class TestData(
var name:String,
var isSelected:Boolean = false
)
//build.gradle
viewBinding {
enabled = true
}
androidx.appcompat.widget.LinearLayoutCompat
默认水平布局;divider属性必须在drawable目录下定义相关xml文件,定义水平或垂直间隔中间隔线的颜色属性和长度或宽度属性
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f22222" />
<size android:height="0.8dp" />
</shape>
style属性可通过values目录下定义文件设置风格属性
//layout,该布局内的控件均按默认水平排列
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:divider="@drawable/divider_item"//各个LinearLayoutCompat之间的分割线样式
app:showDividers="middle|beginning">
<androidx.appcompat.widget.LinearLayoutCompat
//没有设置orientation则默认为水平
style="@style/ll_menu_item_style"
android:layout_width="match_parent">
<Button
.../>
<Button
.../>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
//style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ll_menu_item_style">
<item name="android:layout_height">wrap_content</item>
<item name="android:minHeight">60dp</item>
<item name="android:paddingTop">5dp</item>
<item name="android:paddingBottom">5dp</item>
<item name="android:paddingStart">16dp</item>
<item name="android:gravity">center_vertical</item>
<item name="android:paddingEnd">16dp</item>
</style>
</resources>
LinearLayout控件相比LinearLayoutCompat没有自动设置间隔线的操作,需要用view来设置每个间隔线。
单选按钮,为单选按钮组设置监听器
RadioGroup radGroup = (RadioGroup) findViewById(R.id.radioGroup);
//为radioGroup设置一个监听器:setOnCheckedChanged()
radGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton radBtn = (RadioButton) findViewById(checkedId);
Toast.makeText(getApplicationContext(), "按钮组值发生改变,你选了" + radBtn .getText(), Toast.LENGTH_LONG).show();
}
});
dependencies {
val nav_version = "2.5.3"
implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
}
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"//固定写法
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"//确保NavHostFragment拦截系统返回按钮。只能有一个默认 NavHost。如果同一布局(例如,双窗格布局)中有多个宿主,请务必仅指定一个默认 NavHost
app:navGraph="@navigation/nav_graph" />//与导航图相关联
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/fragmentA">//初始显示页面
<fragment
android:id="@+id/fragmentA"
android:name="com.example.navi.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a" >
<action
android:id="@+id/action_fragmentA_to_fragmentB"
app:destination="@id/fragmentB" />
</fragment>
<fragment
android:id="@+id/fragmentB"
android:name="com.example.navi.FragmentB"
android:label="fragment_b"
tools:layout="@layout/fragment_b" >
<action
android:id="@+id/action_fragmentB_to_fragmentC"
app:destination="@id/fragmentC" />
</fragment>
<fragment
android:id="@+id/fragmentC"
android:name="com.example.navi.FragmentC"
android:label="fragment_c"
tools:layout="@layout/fragment_c" />
</navigation>
class FragmentA : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_a, container, false)
view.findViewById<Button>(R.id.button).setOnClickListener {
findNavController().navigate(R.id.action_fragmentA_to_fragmentB)
}
return view
}
}