- Android 应用界面
界面是布局和微件的层次结构形式构建而成。布局是 ViewGroup 对象,即控制其子视图在屏幕上的放置方式的容器。微件是 View 对象,即按钮和文本框等界面组件。
- 应用组件
应用组件是 Android 应用的基本构建块。每个组件都是一个入口点,系统或用户可通过该入口点进入您的应用。有些组件会依赖于其他组件。
共有四种不同的应用组件类型:
• Activity
• 服务
• 广播接收器
• 内容提供程序
- 清单文件
在 Android 系统启动应用组件之前,系统必须通过读取应用的清单文件 (AndroidManifest.xml) 确认组件存在。您的应用必须在此文件中声明其所有组件,该文件必须位于应用项目目录的根目录中。
- 应用资源
应用资源是指代码使用的附加文件和静态内容,例如位图、布局定义、界面字符串、动画说明等。应将各类资源放入项目 res/ 目录的特定子目录中。
- 布局容器
布局可定义应用中的界面结构(例如 Activity 的界面结构)。布局中的所有元素均使用 View 和 ViewGroup 对象的层次结构进行构建。View 通常绘制用户可查看并进行交互的内容。然而,ViewGroup 是不可见容器,用于定义 View 和其他 ViewGroup 对象的布局结构,如图 所示。
View 对象通常称为“微件”,可以是众多子类之一,例如 Button 或 TextView。ViewGroup 对象通常称为“布局”,可以是提供其他布局结构的众多类型之一,例如 LinearLayout 或 ConstraintLayout。
- Activity
Activity类是 Android 应用的关键组件,而 Activity 的启动和组合方式则是该平台应用模型的基本组成部分。应用中的一个 Activity 会被指定为主 Activity,这是用户启动应用时出现的第一个屏幕。然后,每个 Activity 可以启动另一个 Activity,以执行不同的操作。用中的各个 Activity 协同工作形成统一的用户体验,但每个 Activity 与其他 Activity 之间只存在松散的关联,应用内不同 Activity 之间的依赖关系通常很小。
一个 Activity 在其生命周期中会经历多种状态。
- 在 Activity 之间导航
在应用的生命周期中,应用很可能会多次进入和退出 Activity。例如,用户可以点按设备的返回按钮,或者 Activity 可能需要启动不同的 Activity。 可以使用 startActivity() 或 startActivityForResult() 方法启动新 Activity。这两种方法都需要传入一个 Intent 对象。
- 任务
任务是用户在执行某项工作时与之互动的一系列 Activity 的集合。
- 片段
Fragment 表示 FragmentActivity 中的行为或界面的一部分。您可以在一个 Activity 中组合多个片段,从而构建多窗格界面,并在多个 Activity 中重复使用某个片段。您可以将片段视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,并且您可以在 Activity 运行时添加或移除片段(这有点像可以在不同 Activity 中重复使用的“子 Activity”)。
与 Activity 生命周期协调一致
片段所在 Activity 的生命周期会直接影响片段的生命周期,其表现为,Activity 的每次生命周期回调都会引发每个片段的类似回调。
关联Activity
- 使用 XML 向 Activity 添加 Fragment
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <fragment android:name="com.example.android.fragments.HeadlinesFragment" android:id="@+id/headlines_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.android.fragments.ArticleFragment" android:id="@+id/article_fragment" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>
- 使用支持库 API 调用 getSupportFragmentManager() 以获取 FragmentManager。然后,调用 beginTransaction() 以创建 FragmentTransaction,并调用 add() 以添加 Fragment。
在 Fragment 之间传递数据
- 平级Fragment
getParentFragmentManager().setFragmentResultListener("key", this, new FragmentResultListener() { @Override public void onFragmentResult(@NonNull String key, @NonNull Bundle bundle) { // We use a String here, but any type that can be put in a Bundle is supported String result = bundle.getString("bundleKey"); // Do something with the result... } });
另一个framgment设置结果
Bundle result = new Bundle(); result.putString("bundleKey", "result"); getParentFragmentManager().setFragmentResult("requestKey", result);
- 在父级 Fragment 和子级 Fragment 之间传递结果
如需将结果从子级 Fragment 传递到父级 Fragment,父级 Fragment 在调用 setFragmentResultListener() 时应使用 getChildFragmentManager() 而不是 getParentFragmentManager()。
getChildFragmentManager().setFragmentResultListener("key", this, new FragmentResultListener() { @Override public void onFragmentResult(@NonNull String key, @NonNull Bundle bundle) { String result = bundle.getString("bundleKey"); // Do something with the result.. } });
- 与其他 Fragment 通信
通过共享的 ViewModel 或关联的 Activity 。
o 与 Activity 通信
片段可通过 getActivity() 访问 FragmentActivity 实例,并轻松执行在 Activity 布局中查找视图等任务
View listView = getActivity().findViewById(R.id.list);
Activity 也可使用 findFragmentById() 或 findFragmentByTag(),通过从 FragmentManager 获取对 Fragment 的引用来调用片段中的方法。
代码部分:
1.MyAdapter.java
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null){ // 初始化viewHolder viewHolder = new ViewHolder(); LayoutInflater inflater = LayoutInflater.from(context); convertView = inflater.inflate(R.layout.item_list, null); convertView.setTag(viewHolder); }else{ // 复用旧对象 viewHolder = (ViewHolder)convertView.getTag(); } // 设置textview内容 viewHolder.textView.setText(contents.get(position)); return convertView; }
2.ListActivity.java
void getData2(){ final TextView textView = (TextView) findViewById(R.id.text); // ... // 初始化 RequestQueue. RequestQueue queue2 = Volley.newRequestQueue(this); // 发起一个StringRequest 请求指定网址 StringRequest stringRequest = new StringRequest(Request.Method.GET, "https://www.gcu.edu.cn/main.htm", new Response.Listener<String>() { @Override public void onResponse(String response) { // 在textview控件上显示最多500个字符的内容 textView.setText("Response is: "+ response.substring(0,500)); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // 有错误是,显示: 请求数据报错! textView.setText("请求数据报错!"); } }); // 放置到调度队列. queue2.add(stringRequest); }
3.MyModel. java
public class MyModel extends ViewModel { private MutableLiveData<String> msg; private MutableLiveData<Integer> count; private MutableLiveData<List<ImageInfo>> data; public MutableLiveData<Integer> getCount() { if (count == null) { count = new MutableLiveData<>(); } return count; } public MutableLiveData<String> getMsg() { if (msg == null) { msg = new MutableLiveData<>(); } return msg; } public MutableLiveData<List<ImageInfo>> getData() { if(data == null){ data = new MutableLiveData<>(); } return data; } }
4.MainActivity.java
public class MainActivity extends AppCompatActivity { public static final String INFOKEY = "com.gcu.simple.infokey"; TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.textView); } public void openMessage(View view){ Intent intent = new Intent(this, InfoActivity.class); String msg = textView.getText().toString(); intent.putExtra(INFOKEY, msg); startActivity(intent); } public void listBtn(View view){ Intent intent = new Intent(this, ListActivity.class); startActivity(intent); } }
5.activity main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0"> <Button android:id="@+id/btn_msg" android:text="查看消息" android:onClick="openMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" /> <TextView android:id="@+id/textView" android:text="什么都没有" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginBottom="8dp" /> <Button android:id="@+id/btn_data" android:text="数据更新及列表" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="listBtn" /> <Button android:id="@+id/btn_style" style="@style/button_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="使用样式" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
6.styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> </style> <style name="button_text" parent="TextAppearance.AppCompat.Widget.ActionBar.Title"> <item name="android:textSize">20sp</item> <item name="android:textColor">#FF0000</item> <item name="android:textStyle">italic</item> </style> <style name="button_text.mytextstyle" > <item name="android:textSize">30sp</item> <item name="android:textStyle">bold</item> </style> </resources>