android基础01 - Activity、控件布局、Fragment

四大组件

  1. Activity
  2. Service
  3. BroadcastReceiver
  4. ContentProvider

使用资源,代码中使用 R.string.app_name ,XML中使用 @string/app_name

Activity

一个Activity注意3部分:

  1. 后端文件 src/main/java/com/example/app/XXXActivity.kt
    在重写的 onCreate 方法中 setContentView(R.layout.activity_main)
    使用资源 R.layout.activity_app R.string.app_name R.资源分类.资源名
    省略 findViewById:https://blog.csdn.net/guolin_blog/article/details/113089706
  2. 前端页面 src/res/layout/activity_app.xml
    使用资源 使用已有id:@id/button1 定义一个新id:@+id/button2
  3. 在 AndroidManifest.xml 中配置
    一般创建Activity时自动添加

Intent 实现跳转

不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可用于启动Activity、启动Service以及发送广播等场景

  1. 显式
    // 使用ViewBinding简化了 findViewById
            var inflate = ActivityMainBinding.inflate(layoutInflater)
            inflate.button01.setOnClickListener { 
                val intent = Intent(this, SecondActivity::class.java) // 显示Intent,跳到别的Activity
                startActivity(intent)
            }

    通过返回键销毁新Activity返回到旧的

  2. 隐式
    不明确指出想要启动哪一个Activity,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的Activity去启动。
    在 AndroidManifest.xml 中配置 intent-filter 执行处理的 action 和 category
            <activity
                android:name=".SecondActivity"
                android:exported="false">
                <meta-data
                    android:name="android.app.lib_name"
                    android:value="" />
                <intent-filter>
                    <action android:name="com.example.activitytest.ACTION_START"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                    <category android:name="com.example.activitytest.MY_CATEGORY"/>
                </intent-filter>
            </activity>
    inflate.button01.setOnClickListener {
                // val intent = Intent(this, SecondActivity::class.java)        // 显式
                val intent = Intent("com.example.activitytest.ACTION_START") // 隐式
                intent.addCategory("com.example.activitytest.MY_CATEGORY")   // 指定category,和action一起工作,可省略
                startActivity(intent)
            }
  3. 通过data隐式响应
    <activity android:name=".ThirdActivity">
        <intent-filter tools:ignore="AppLinkUrlError">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="https" />    android:host  android:port  android:path  android:mimeType
        </intent-filter>
    </activity>
    button1.setOnClickListener {
         val intent = Intent(Intent.ACTION_VIEW)
         intent.data = Uri.parse("https://www.baidu.com")
         startActivity(intent)
    }
    
    // 打电话
    val intent = Intent(Intent.ACTION_DIAL)
    intent.data = Uri.parse("tel:10086")
  4. 向Activity传数据
    putExtra()  getStringExtra() getIntExtra()
    button1.setOnClickListener {
         val data = "Hello SecondActivity"
         val intent = Intent(this, SecondActivity::class.java)
         intent.putExtra("extra_data", data)
         startActivity(intent)
    }
    
    // 其他 Activity
    class SecondActivity : AppCompatActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             setContentView(R.layout.second_layout)
             val extraData = intent.getStringExtra("extra_data")
             Log.d("SecondActivity", "extra data is $extraData")
         }
    }
  5. 返回数据给上个activity
    button1.setOnClickListener {
         val intent = Intent(this, SecondActivity::class.java)
         startActivityForResult(intent, 1) // 第二个请求吗用于判断跳转来源
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { // 接受结果
        super.onActivityResult(requestCode, resultCode, data)
            when (requestCode) {
            1 -> if (resultCode == RESULT_OK) {
                val returnedData = data?.getStringExtra("data_return")
                    Log.d("FirstActivity", "returned data is $returnedData")
                }
        }
    }
    
    
    // 跳转到的Activity
    class SecondActivity : AppCompatActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             setContentView(R.layout.second_layout)
             // 手动返回
             button2.setOnClickListener {
                 val intent = Intent()
                 intent.putExtra("data_return", "Hello FirstActivity")
                 setResult(RESULT_OK, intent) // 第一个参数还可返回 RESULT_CANCELED,
                 finish()
             }
         }
        // 通过返回键返回
        override fun onBackPressed() {
            val intent = Intent()
            intent.putExtra("data_return", "Hello FirstActivity")
            setResult(RESULT_OK, intent)
            finish()
        }
    }

运行状态

  1. 完整生存期。Activity在onCreate()方法和onDestroy()方法之间所经历的就是完整生存期。一般情况下,一个Activity会在onCreate()方法中完成各种初始化操作,而在onDestroy()方法中完成释放内存的操作。
  2. 可见生存期。Activity在onStart()方法和onStop()方法之间所经历的就是可见生存期。在可见生存期内,Activity对于用户总是可见的,即便有可能无法和用户进行交互。我们可以通过这两个方法合理地管理那些对用户可见的资源。比如在onStart()方法中对资源进行加载,而在onStop()方法中对资源进行释放,从而保证处于停止状态的Activity不会占用过多内存。
  3. 前台生存期。Activity在onResume()方法和onPause()方法之间所经历的就是前台生存期。在前台生存期内,Activity总是处于运行状态,此时的Activity是可以和用户进行交互的,我们平时看到和接触最多的就是这个状态下的Activity。

后台的Activity被销毁后,返回页面时会调用onCreate再构建一次,此时会丢失临时数据

// 此处的Bundle会作为onCreate方法的参数传入
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val tempData = "Something you just typed"
        outState.putString("data_key", tempData)
    }

 启动模式

在AndroidManifest.xml中通过给标签指定 android:launchMode属性来选择启动模式

  1. standard
    默认,启动后在栈顶创建,再启动时不管是否栈中存在,一定再创建一个
  2. singleTop
    处于栈顶时不再创建,否则创建新的
    <activity
         android:name=".FirstActivity"
         android:launchMode="singleTop"
         android:label="This is FirstActivity">
             <intent-filter>
             <action android:name="android.intent.action.MAIN"/>
             <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
    </activity>
  3. singleTask
    创建时,如果没有新的则创建;否则将栈中其上的全部销毁,使其到栈顶
    <activity
        android:name=".FirstActivity"
        android:launchMode="singleTask"
        android:label="This is FirstActivity">
            <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
    </activity>
  4. singleInstance
    启用一个新的返回栈来管理这个Activity(其实如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈)。
    程序的某个Activity允许其他程序调用,这种模式下,会有一个单独的返回栈来管理这个Activity,不管是哪个应用程序来访问这个Activity,都共用同一个返回栈,也就解决了共享Activity实例的问题。
    <activity android:name=".SecondActivity" android:launchMode="singleInstance">
         <intent-filter>
             <action android:name="com.example.activitytest.ACTION_START" />
             <category android:name="android.intent.category.DEFAULT" />
             <category android:name="com.example.activitytest.MY_CATEGORY" />
         </intent-filter>
    </activity>

开发技巧

定位当前 Activity

创建一个BaseActivity 用于继承

open class BaseActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("BaseActivity", javaClass.simpleName)
    }
}

随时退出程序

要用一个专门的集合对所有的Activity进行管理,实现一个按键退出所有Activity

// 单例列表
object ActivityCollector {
    private val activities = ArrayList<Activity>()

    fun addActivity(activity: Activity) {
        activities.add(activity)
    }
    fun removeActivity(activity: Activity) {
        activities.remove(activity)
    }
    fun finishAll() {
        for (activity in activities) {
            // 注意在销毁Activity之前,我们需要先调用activity.isFinishing来判断Activity是否正在销毁中,因为Activity还可能通过按下Back键等方式被销毁
            if (!activity.isFinishing) {
                activity.finish()
            }
        }
        activities.clear()
        // 杀死当前进程
        android.os.Process.killProcess(android.os.Process.myPid())
    }
}

open class BaseActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("BaseActivity", javaClass.simpleName)
        ActivityCollector.addActivity(this)
    }
    override fun onDestroy() {
        super.onDestroy()
        ActivityCollector.removeActivity(this)
    }
}

// 一个按键退出所有
button3.setOnClickListener {
    ActivityCollector.finishAll()
}

启动 Activity 最佳写法

val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("param1", "data1")
intent.putExtra("param2", "data2")
startActivity(intent)

上面正确,但是容易出现问题。理不清关系

class SecondActivity : BaseActivity() {
    // ...
    // 所有定义在companion object中的方法都可以使用类似于Java静态方法的形式调用
    companion object {
        fun actionStart(context: Context, data1: String, data2: String) {
            val intent = Intent(context, SecondActivity::class.java)
            intent.putExtra("param1", data1)
            intent.putExtra("param2", data2)
            context.startActivity(intent)
        }
    }
}

// 它的使用
button1.setOnClickListener {
     SecondActivity.actionStart(this, "data1", "data2")
}

UI 开发

控件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|center_horizontal"
        android:textColor="#00ff00"
        android:textSize="24sp" 
        android:text="This is TextView"/>
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAllCaps="false"  //取消大写
        android:text="Button" />
    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type something here" // 提示文本
        android:maxLines="2" // 内容过长时选择换行
    />
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_1" // 将图片资源放在 src/drawable 目录下
    />
    // 默认是不停转的圆圈
    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" // 每个控件都有这个属性,默认visible可见,invisible透明,gone隐藏
        // style="?android:attr/progressBarStyleHorizontal" // 指定为水平进度条
    />
</LinearLayout>
class MainActivity : AppCompatActivity(), View.OnClickListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
            button.setOnClickListener(this)
        }
        override fun onClick(v: View?) {
            when (v?.id) {
            R.id.button -> {
                val inputText = editText.text.toString()
                Toast.makeText(this, inputText, Toast.LENGTH_SHORT).show()
                imageView.setImageResource(R.drawable.img_2)
            }
            R.id.button1 -> {
                if (progressBar.visibility == View.VISIBLE) {
                    progressBar.visibility = View.GONE
                } else {
                    progressBar.visibility = View.VISIBLE
                }
            }
            R.id.水平进度条 -> {
                progressBar.progress = progressBar.progress + 10
            }
            R.id.弹出对话框 -> {
                AlertDialog.Builder(this).apply {
                    setTitle("This is Dialog")
                    setMessage("Something important.")
                    setCancelable(false)
                    setPositiveButton("OK") { dialog, which ->
                        //...
                    }
                    setNegativeButton("Cancel") { dialog, which ->
                        //...
                    }
                    show()
                }
            }
        }
    }
}

布局

  1. 线性布局
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"  // horizontal
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top" // 相对位置,horizontal布局只能指定垂直方向,vertical只能指定水平方向
        android:layout_weight="1"    // 通过指定权重进行相对布局,宽度或高度应为0dp。
                                     // 某行中按钮控件指定宽度,输入框指定权重,可实现按钮宽度注定,输入框占据剩余宽度
        android:text="Button 1" />
        <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="Button 2" />
    </LinearLayout>
  2. 相对布局
    相对父布局
    // 通过相对定位,让控件出现在任何位置
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    // 相对父布局定位,让Button 1和父布局的左上角对齐,Button 2和父布局的右上角对齐,
    // Button 3居中显示,Button 4和父布局的左下角对齐,Button 5和父布局的右下角对齐
        <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="Button 1" />
        <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="Button 2" />
        <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Button 3" />
        <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:text="Button 4" />
        <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="Button 5" />
    </RelativeLayout>



    相对控件
     // 控件之间相对
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Button 3" />
        <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/button3"
        android:layout_toLeftOf="@id/button3"
        android:text="Button 1" />
        <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/button3"
        android:layout_toRightOf="@id/button3"
        android:text="Button 2" />
        <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button3"
        android:layout_toLeftOf="@id/button3"
        android:text="Button 4" />
        <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button3"
        android:layout_toRightOf="@id/button3"
        android:text="Button 5" />
    </RelativeLayout>

  3. 帧布局
    所有的控件都会默认摆放在布局的左上角
    帧布局
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:text="This is TextView"/>
        <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="Button"/>
    </FrameLayout>

自定义控件(页面代码复用)

1. 创建布局

所有控件直接或间接继承自View,所有布局直接或间接继承自ViewGroup。ViewGroup是个特殊容器,能包含多个View或多个ViewGroup。

创建一种新的布局,在页面顶端加上一个标题框和后退按钮:

在layout目录下新建一个title.xml布局

// 一个普通页面
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_bg">
    <Button
    android:id="@+id/titleBack"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="5dp"
    android:background="@drawable/back_bg"
    android:text="Back"
    android:textColor="#fff" />
    <TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_weight="1"
    android:gravity="center"
    android:text="Title Text"
    android:textColor="#fff"
    android:textSize="24sp" />
    <Button
    android:id="@+id/titleEdit"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="5dp"
    android:background="@drawable/edit_bg"
    android:text="Edit"
    android:textColor="#fff" />
</LinearLayout>

在页面中调用:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent" >
    <include layout="@layout/title" />
</LinearLayout>

在页面的后端代码中的onCreate中用supportActionBar?.hide()隐藏自带的标题栏

2. 创建控件

为自定义控件添加事件

class TitleLayout(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
    init {
        LayoutInflater.from(context).inflate(R.layout.title, this)
        titleBack.setOnClickListener {
            val activity = context as Activity
            activity.finish()
        }
        titleEdit.setOnClickListener {
            Toast.makeText(context, "You clicked Edit button", Toast.LENGTH_SHORT).show()
        }
    }
}

在activity_main.xml 中使用控件,这时不用编写额外代码,按键也会监听事件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent" >
    <com.example.uicustomviews.TitleLayout
                                           android:layout_width="match_parent"
                                           android:layout_height="wrap_content" />
</LinearLayout>

ListView

最简单使用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <ListView
              android:id="@+id/listView"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
</LinearLayout>
class MainActivity : AppCompatActivity() {
    private val data = listOf("Apple", "Banana", "Orange", "Watermelon",
        "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango",
        "Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape",
        "Pineapple", "Strawberry", "Cherry", "Mango")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val adapter = ArrayAdapter<String>(this,android.R.layout.simple_list_item_1/*内置布局文件,只有一个TextView*/,data)
        listView.adapter = adapter
    }
}

RecyclerView

升级版ListView,定义在AndroidX库中,在项目的build.gradle中添加RecyclerView库的依赖所有版本都可以使用。

Fragment

与Activity类似,主要用于适配平板。

  1. 简单使用
    先定义两个layout的xml文件
    // 左.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Button"
            />
    </LinearLayout>
    
    // 右.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:background="#00ff00"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textSize="24sp"
            android:text="This is right fragment"
            />
    </LinearLayout>

    新建Fragment类

    class LeftFragment : Fragment() {
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.left_fragment, container, false)
        }
    }
    
    class RightFragment : Fragment() {
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.right_fragment, container, false)
        }
    }

    layout.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="horizontal"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" >
        <fragment
                  android:id="@+id/leftFrag"
                  android:name="com.example.fragmenttest.LeftFragment"
                  android:layout_width="0dp"
                  android:layout_height="match_parent"
                  android:layout_weight="1" />
        <fragment
                  android:id="@+id/rightFrag"
                  android:name="com.example.fragmenttest.RightFragment"
                  android:layout_width="0dp"
                  android:layout_height="match_parent"
                  android:layout_weight="1" />
    </LinearLayout>

  2. 动态添加Fragment
    another_right_fragment.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:background="#ffff00"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
        <TextView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_gravity="center_horizontal"
                  android:textSize="24sp"
                  android:text="This is another right fragment"
                  />
    </LinearLayout>

    再创建一个新的Fragment对象

    class AnotherRightFragment : Fragment() {
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.another_right_fragment, container, false)
        }
    }

    将 layout_main 中的右侧fragment 对象更换为 FragmentLayout 布局,它将控件默认放在左上角,十分适合。
    注意要手动添加到返回栈

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            button.setOnClickListener {
                replaceFragment(AnotherRightFragment())
            }
            replaceFragment(RightFragment()) // 调用方法时创建待添加的 Fragment 实例
        }
        private fun replaceFragment(fragment: Fragment) {
            // 获取事务并开启
            val fragmentManager = supportFragmentManager
            val transaction = fragmentManager.beginTransaction()
            // 向容器内添加或替换Fragment,一般用replace() 实现,传入容器id和待添加的Fragment实例
            transaction.replace(R.id.rightLayout, fragment)
            // 添加到程序返回栈
            transaction.addToBackStack(null)
            transaction.commit()
        }
    }
  3. Fragment 与 Activity 之间的通信
    // Activity 获取 Fragment
    val fragment = supportFragmentManager.findFragmentById(R.id.leftFrag) as LeftFragment
    
    // Fragment 获取 Activity
    // 通过调用getActivity()方法来得到和当前Fragment相关联的Activity实例
    
    // Fragment 与 Fragment 通信
    // Fragment先获得一个Activity,再通过它获得其他的Fragment

动态加载布局的技巧

限定符

平板上使用双页模式,手机使用单页模式,自动切换。

在 src/main/res/layout/activity_main.xml 中创建单页页面
在 src/main/res/layout_large/activity_main.xml 中创建双页页面

常见限定符:

最小宽度限定符

创建 layout-sw600dp 文件夹,当分辨率大于等于600dp时使用这个页面。

posted @ 2022-12-31 23:32  某某人8265  阅读(30)  评论(0编辑  收藏  举报