一 、UI基础入门
1.线性布局(LinerLayout)
重要属性
android:orientation: verticle/horhorizontal 方向:垂直/水平
android:layout_weight 权重
android:layout_gravity 重力
2.相对布局(RelativeLayout)
android:layout_centerInParent
android:layout_alignParentLeft
android:layout_alignParentRight
android:layout_alignParentTop
android:layout_alignParentBottom
android:layout_centerHorizontal
android:layout_centerVertical
1.在参照物的某边
android:layout_toLeftOf
android:layout_toRightOf
android:layout_above
android:layout_below
2.和参照物的某边线对齐
android:layout_alignTop
android:layout_alignBottom
android:layout_alignLeft
android:layout_alignRight
3.帧布局(FrameLayout)
android:layout_gravity="center" 重力
android:foreground="@mipmap/ic_launcher" 前景
android:foregroundGravity="right|bottom" 前景重力
4.表格布局(TableLayout)
如果直接往TableLayout中添加控件,那么该控件与屏幕等宽
如果想使多个控件在同一行,那么我们在这些控件外层包裹一对TableRow
并且在这种情况下,控件宽度与内容适配
android:stretchColumns="*" 设置可以伸展的列,直接传列的索引,如果有多列,以,作为分割,*表示全部
android:shrinkColumns 设置可以缩小的列
android:collapseColumns="1" 设置可隐藏的列
5.网格布局(GridLayout)
android:rowCount(行数量)
android:columnCount(列数量)
android:layout_row(位于第几行)
android:layout_rowSpan(跨几行)
6.约束布局(ConstraintLayout)
app:layout_constraint方位_to方位Of="?"
? : 1. parent 2.引用其他控件id
当前控件的某个方位和另一个参照物的某个方位对齐
app:layout_constraintLeft_toLeftOf 相当于RelativeLayout的alignLeft属性
app:layout_constraintRight_toRightOf 相当于RelativeLayout的alignRight属性
app:layout_constraintTop_toTopOf 相当于RelativeLayout的alignTop属性
app:layout_constraintBottom_toBottomOf 相当于RelativeLayout的alignBottom属性
app:layout_constraintStart_toStartOf 同Left_toLeftOf
app:layout_constraintEnd_toEndOf 同Right_toRightOf
当前控件的A侧会在参照物的B侧
app:layout_constraintLeft_toRightOf 相当于RelativeLayout的toRightOf
app:layout_constraintRight_toLeftOf 相当于RelativeLayout的toLeftOf
app:layout_constraintTop_toBottomOf 相当于RelativeLayout的below
app:layout_constraintBottom_toTopOf 相当于RelativeLayout的above
app:layout_constraintStart_toEndOf 同Left_toRightOf
app:layout_constraintEnd_toStartOf 同Right_toLeftOf
app:layout_constraintVertical_bias="0.53" 垂直偏移量,0.5在正中间
app:layout_constraintHorizontal_bias="0.53" 水平偏移量,0.5在正中间
7.UI基础控件
View
处理文本内容的View(TextView)
1.TextView的继承关系
- 对长文本惊醒显示处理
- 支持HTML代码
- 内容有样式、链接效果
2.被点击的View(Button)
Button注册点击事件的方法
1. 自定义内部类
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="通过自定义内部类实现点击事件"/>
//1.获取按钮
Button btn1 = findViewById(R.id.btn1);
//点击事件:被点击时被触发的事件
MyClickListener mcl = new MyClickListener();
//2.为按钮注册点击事件监听器
btn1.setOnClickListener(mcl);
class MyClickListener implements View.OnClickListener{
@Override
public void onClick(View view) {
//在控制台输出一条语句
Log.e("TAG","刚刚点击的按钮时注册了内部类监听器对象的按钮");
}
}
2. 匿名内部类
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="通过匿名内部类实现点击事件"/>
//匿名内部类适用于有唯一操作的按钮
Button btn2 = findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//在控制台输出
Log.e("TAG","==========匿名内部类==========");
}
});
3. 当前Activity去实现事件接口
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="通过当前Activity去实现点击事件接口"/>
Button btn3 = findViewById(R.id.btn3);
btn3.setOnClickListener(this);
@Override
public void onClick(View view) {
Log.e("TAG","用本类实现了OnClickListener");
}
4. 在当前布局文件中添加点击事件属性
<Button
android:id="@+id/btn4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="在xml文件中绑定"
android:onClick="myClick"/>
<Button
android:id="@+id/btn5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="在xml文件中绑定2"
android:onClick="myClick"/>
//参数:被点击的控件对象
public void myClick(View v){
switch (v.getId()){
case R.id.btn4:
Log.e("TAG","btn4======");
break;
case R.id.btn5:
Log.e("TAG","btn5======");
break;
}
}
3.处理图片内容的View(ImageView)
用来显示和控制图像的控件,可以对它进行放大,缩小,旋转等操作。 常见属性有:
android:src
android:background
4.接收用户信息输入的View(EditText)
android:inputType
android:hint
android:maxLength
5.进度条类的View(ProgressBar)
进度条,默认情况下是圆形,没有刻度,这是一个不断旋转的动画效果。通过设置style,可以显示传统的水平带刻度进度条。
<!--
进度条:默认样式是转圈。修改样式需设置风格
style 设置风格progressBarStyleHorizontal(水平进度条)
android:progress="" 设置进度
android:max="" 设置最大值,默认100
android:indeterminate="true" 设置进度条一直滚动
-->
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:progress="30"
android:max="200"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="true"/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"/>
final ProgressBar progressBar = findViewById(R.id.progress);
progressBar.setProgress(80);
//在Android中,4.0以后是不能直接在线程中操作控件的
//进度条是个特例
new Thread(){
@Override
public void run() {
for(int i = 1 ; i <= 100 ; i++) {
progressBar.setProgress(i);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
通用属性
二 、UI常用组件
1.Activity入门
1.Activity之间的跳转
<TextView
android:id="@+id/titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"/>
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button"/>
// 通过findViewById将layout中的控件找出来,并转化成View
final TextView textView = findViewById(R.id.titleTextView);
// 打到button这个view
Button button = findViewById(R.id.button);
// 设置点击事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 为textView动态设置文本
textView.setText(getString(R.string.app_name));
// 跳转到一个NewActivity
Intent intent = new Intent(TestActivity.this, TestActivity.class);
startActivity(intent);
}
});
2.Activity四种启动模式
//设置启动模式:android:launchMode="singleTop"
<activity android:name=".TestActivity"
android:launchMode="singleTop"
android:label="testActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
1.standard
2.singleTop
3.singleTask
4.singleInstance
2.Android菜单创建和使用
1.Menu分类
1.选项菜单(OptionMenu)
选项菜单是一个应用的主要单项,用于放置对应用产生全局影响的操作,如搜索/设置。
1.通过XML资源来设计menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!--showAsAction属性值:always :直接在标题栏显示
never:不显示
withText:控制图标和文本一起显示
ifRoom:有空间就显示-->
<item android:title="保存"
android:id="@+id/save"
android:icon="@mipmap/ic_launcher"
app:showAsAction="always"/>
<item android:title="设置"
android:id="@+id/setting"/>
<item android:title="更多操作" >
<menu >
<item android:title="退出"
android:id="@+id/exit"/>
<item android:title="子菜单2" />
<item android:title="子菜单3" />
</menu>
</item>
</menu>
public boolean onCreateOptionsMenu(Menu menu) {
//加载菜单资源
//通过XML资源来设计menu
getMenuInflater().inflate(R.menu.option,menu);
//一定要记得返回true,否则菜单不显示
return true;
}
2.纯java代码设计menu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//纯java代码设计menu
/*
设置
更多
添加
删除
*/
// Menu
//参数1:组id 参数2:菜单项id 参数3:序号 参数4:设置
menu.add(1, 1, 1,"设置");
SubMenu sub = menu.addSubMenu(1,2,2,"更多");
// SubMenu
sub.add(2,3,1,"添加");
sub.add(2,4,2,"删除");
//一定要记得返回true,否则菜单不显示
return true;
}
//OptionMenu菜单项的选中方法
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case 1:
Toast.makeText(this,"设置",Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(this,"更多",Toast.LENGTH_SHORT).show();
break;
case 3:
Toast.makeText(this,"添加",Toast.LENGTH_SHORT).show();
break;
case 4:
Toast.makeText(this,"删除",Toast.LENGTH_SHORT).show();
break;
default:
super.onOptionsItemSelected(item);
}
return true;
}
2.上下文菜单(ContextMenu)
长按某个item不放,就会在屏幕中间弹出ContextMenu。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/delete"
android:title="删除" />
<item android:title="重命名" >
<menu >
<item
android:id="@+id/opera1"
android:title="操作1" />
<item
android:id="@+id/opera2"
android:title="操作2" />
</menu>
</item>
</menu>
//ctx_btn:演示ContextMenu
//1.注册
registerForContextMenu(findViewById(R.id.ctx_btn));
//2.创建 覆盖onCreateContextMenu
//3.菜单项的操作 覆盖onContextItemSelected
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
getMenuInflater().inflate(R.menu.context,menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.delete:
Toast.makeText(this,"删除",Toast.LENGTH_SHORT).show();
break;
case R.id.opera1:
Toast.makeText(this,"操作1",Toast.LENGTH_SHORT).show();
break;
case R.id.opera2:
Toast.makeText(this,"操作2",Toast.LENGTH_SHORT).show();
break;
}
return super.onContextItemSelected(item);
}
如果要为按钮设置上下文操作模式:
//①实现ActionMode CallBack(注释上述代码)
//②在view的长按事件中去启动上下文操作模式
findViewById(R.id.ctx_btn).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
startActionMode(cb);
return false;
}
});
ActionMode.Callback cb = new ActionMode.Callback() {
//创建,在启动上下文操作模式(startActionMode(Callback))时调用
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
Log.e("TAG","创建");
getMenuInflater().inflate(R.menu.context,menu);
return true;
}
//在创建方法后进行调用
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
Log.e("TAG","准备");
return false;
}
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
Log.e("TAG","点击");
switch (menuItem.getItemId()){
case R.id.delete:
Toast.makeText(MainActivity.this,"删除",Toast.LENGTH_SHORT).show();
break;
case R.id.opera1:
Toast.makeText(MainActivity.this,"操作1",Toast.LENGTH_SHORT).show();
break;
case R.id.opera2:
Toast.makeText(MainActivity.this,"操作2",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
//上下文操作模式结束时被调用
@Override
public void onDestroyActionMode(ActionMode actionMode) {
Log.e("TAG","结束");
}
};
3.弹出菜单(PopupMenu)
一个模态形式展示的弹出风格的菜单,绑在某个View上,一版出现在被绑定的View的下方。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/copy"
android:title="复制" />
<item
android:id="@+id/paste"
android:title="粘贴" />
</menu>
//popup_btn:演示PopupMenu
final Button popupBtn = findViewById(R.id.popup_btn);
popupBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//①实例化PopupMenu对象 (参数2:被锚定的view)
final PopupMenu menu = new PopupMenu(MainActivity.this,popupBtn);
//②加载菜单资源:利用MenuInflater将Menu资源加载到PopupMenu.getMenu()所返回的Menu对象中
//将R.menu.xx对于的菜单资源加载到弹出式菜单中
menu.getMenuInflater().inflate(R.menu.popup,menu.getMenu());
//③为PopupMenu设置点击监听器
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.copy:
Toast.makeText(MainActivity.this,"复制",Toast.LENGTH_SHORT).show();
break;
case R.id.paste:
Toast.makeText(MainActivity.this,"粘贴",Toast.LENGTH_SHORT).show();
break;
}
return false;
}
});
//④千万不要忘记这一步,显示PopupMenu
menu.show();
}
});
2.XML定义Menu的优势
- 清晰的菜单结构
- 将菜单内容与应用的逻辑代码分离
- 资源适配更容易
3.XML定义的Menu不显示
- onCreateOptionsMenu()方法必须返回true
- onOptionsItemSelected方法返回true
- 调用父类的默认实现
3.Android对话框处理
1.AlertDialog
2.自定义Dialog
3.PopupWindow
4.Activity生命周期
1.Activity生命周期
public class MainActivity extends AppCompatActivity {
//单个Activity的生命周期:
//1.正常启动onCreate-->onStart-->onReusme , 正常退出onPause-->onStop-->onDestory,
// 再次启动onCreate-->onStart-->onResume
//2.已经处于前台的Activity,点击主页按钮离开当前Activity,OnPause-->onStop,
// 回到Activity:onRestart-->onStart-->onResume
//3.Activity不可操作onPause-->onStop(如:息屏,打开了其他Activity),而应用被强行杀死了,
//再回到Activity,onCreate-->onStart-->onResume
//多个Activity切换时
//当启动另一个Activity时,当前Activity:onPause-->onStop,当点击返回按钮,
//使另一个Activity退出时,当前Activity:onRestart-->onStart-->onResume
//对话框存在时
//1.普通对话框对生命周期没有任何影响
//2.如果有个Activity伪装成对话框模式,那么当它启动时,之前的Activity:onPause
//“对话框”消失后,回调onResume再次回到前台
//创建
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("TAG","onCreate----创建");
}
//启动
@Override
protected void onStart() {
super.onStart();
Log.e("TAG","onStart----启动");
}
//恢复
@Override
protected void onResume() {
super.onResume();
Log.e("TAG","onResume----恢复");
}
//暂停
@Override
protected void onPause() {
super.onPause();
Log.e("TAG","onPause----暂停");
}
//停止
@Override
protected void onStop() {
super.onStop();
Log.e("TAG","onStop----停止");
}
//销毁
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("TAG","onDestroy----销毁");
}
//重启
@Override
protected void onRestart() {
super.onRestart();
Log.e("TAG","onRestart----重启");
}
}
2.Activity启动方式
1.显式启动
<Button
android:id="@+id/btn1"
android:onClick="myclick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显式打开第二个界面"/>
public void myclick(View view){
switch (view.getId()){
case R.id.btn1://启动第二个Ativity
//意图
//参数1:环境上下文,当前环境(this)。
//参数2:待跳转的Activity的类对象
Intent it = new Intent(this, Main2Activity.class);
startActivity(it);//启动Activity
break;
}
}
2.隐式启动
1.隐式启动系统Activity(打开浏览器)
<Button
android:id="@+id/btn2"
android:onClick="myclick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="隐式启动系统Activity(打开浏览器)"/>
public void myclick(View view){
switch (view.getId()){
case R.id.btn2://隐式启动系统Activity
//参数1:字符串(某Activity的别名)
//参数2:打开的路径,通过 协议 来具体的确定打开什么Activity
Intent it2 = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.baidu.com")); //tel:13338889999
startActivity(it2);
break;
}
}
2.隐式启动普通Activity
<Button
android:id="@+id/btn3"
android:onClick="myclick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="隐式启动普通Activity" />
public void myclick(View view){
switch (view.getId()){
//隐式启动普通Activity
//abc为别名,需要在AndroidManifest.xml文件里面去添加
case R.id.btn3:
Intent it3 = new Intent("abc");
startActivity(it3);
break;
}
<activity android:name=".Main2Activity">
<intent-filter>
<!--取别名-->
<action android:name="abc"/>
<!--分组-->
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
3.startActivityForResult
<Button
android:id="@+id/btn4"
android:onClick="myclick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="带结果返回的方式启动Activity" />
public void myclick(View view){
switch (view.getId()){
case R.id.btn4:
Intent it4 = new Intent(this,Main2Activity.class);
//参数:请求码
startActivityForResult(it4,1000);
break;
}
}
//如果时通过startActivityForResult的方式启动了第二个Activity
//当第二个Activity处理结束后,再回到的当前Activity时,一定会自动回调onActivityResult
//在该方法中我们可以处理第二个Activity返回的结果(如:拍照后得到的照片,从图库中选取的图片)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//resultCode: 0 , RESULT_CANCEL 取消 -1,RESULT_OK 正确处理完后返回
if(resultCode == RESULT_OK) {
//requestCode:用来区分该结果是来自于哪个Activity
if (requestCode == 1000) {
Log.e("TAG", "自动进入了onActivityResult,requestCode=" + requestCode + ",resultCode=" + resultCode);
Log.e("TAG","返回的数据是:" + data.getStringExtra("myMsg"));
}
}
}
TextView txt = findViewById(R.id.txt);
txt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent it = new Intent(); //此时的意图不作为跳转界面使用,而是用来传递数据
it.putExtra("myMsg", "这是来自第二个界面的信息");
//设置结果
//参数1:结果码,在上一个界面的onActivityResult方法中通过resultCode获取
//参数2:意图对象,主要作用:放数据,在上一个界面的onActivityResult方法中通过data获取
setResult(RESULT_OK, it);
finish();
}
});
3.Activity信息传递
1.传递普通数据
<Button
android:id="@+id/btn5"
android:onClick="myclick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显式打开第二个界面,并传递数据"/>
public void myclick(View view){
switch (view.getId()){
case R.id.btn5://启动第二个Ativity
//意图
//参数1:环境上下文,当前环境(this)。
//参数2:待跳转的Activity的类对象
Intent it5 = new Intent(this,Main2Activity.class);
it5.putExtra("msg1","这是数据1");
it5.putExtra("msg2",100);
break;
}
}
//如果要获取上一个界面传来的数据,那么首先要获取做启动的意图
Intent it = getIntent();
String msg1 = it.getStringExtra("msg1");
//参数1:数据的name,参数2:默认值
int msg2 = it.getIntExtra("msg2", 0);
TextView txt = findViewById(R.id.txt);
txt.setText(msg1+" "+msg2);
2.传递对象数据
<Button
android:id="@+id/btn6"
android:onClick="myclick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显式打开第二个界面,并传递数据"/>
//序列化:
//1.想把内存中的对象保存到一个文件或数据库中时
//2.像利用套接字Socket在网络中传递对象
public class Student implements Serializable {
private String name;
private int age;
private String gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}
public void myclick(View view){
switch (view.getId()){
case R.id.btn6://启动第二个Ativity
//意图
//参数1:环境上下文,当前环境(this)。
//参数2:待跳转的Activity的类对象
Intent it6 = new Intent(this,Main2Activity.class);
//利用Intent传递对象
Student s = new Student("张三",22,"男");
it6.putExtra("stu",s);
break;
}
}
//如果要获取上一个界面传来的数据,那么首先要获取做启动的意图
Intent it = getIntent();
//获取序列化对象
Student stu = (Student) it.getSerializableExtra("stu");
if (stu != null) {
TextView txt = findViewById(R.id.txt);
txt.setText(stu.getName() + " " + stu.getAge() + " " + stu.getGender());
}
5.Fragment创建及使用
1.Fragment设置思想
为什么需要Fragment
2.Fragment VS Activity
- Fragment是到Android3.0+以后
- 一个Activity可以运行多个Fragment
- Fragment不能脱离Activity而存在
- Activity是屏幕的主体,而Fragment是Activity的一个组成元素
3.Fragment生命周期
public class Fragment1 extends Fragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.e("TAG","onAttach--Fragment与Activity关联");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("TAG","onCreate--Fragment创建好了");
}
//Fragment创建视图
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.e("TAG","onCreateView--Fragment视图创建好了");
return inflater.inflate(R.layout.fragment_fragment1, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.e("TAG","onActivityCreated--Activity已经创建好了");
}
@Override
public void onStart() {
super.onStart();
Log.e("TAG","onStart--Fragment启动");
}
@Override
public void onResume() {
super.onResume();
Log.e("TAG","onResume--Fragment显示");
}
@Override
public void onPause() {
super.onPause();
Log.e("TAG","onPause--Fragment暂停");
}
@Override
public void onStop() {
super.onStop();
Log.e("TAG","onStop--Fragment停止");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.e("TAG","onDestroyView--Fragment视图销毁");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TAG","onDestroy--Fragment销毁");
}
@Override
public void onDetach() {
super.onDetach();
Log.e("TAG","onDetach--与Activity解除关联");
}
}
4. 加载Fragment
1.静态加载:XML
//静态加载:通过android:name属性指定Fragment的路径
//需要新建一个名为Fragment1的Fragment
<fragment
android:id="@+id/fragment1"
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:name="com.example.fragmentdemo.Fragment1"/>
2.动态加载
<FrameLayout
android:id="@+id/container"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fragment1"></FrameLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//FragmentManager FragmentTransaction
//1.获取Fragment管理器
FragmentManager manager = getSupportFragmentManager();
//2.获取Fragment事务(/开启事务)
FragmentTransaction transaction = manager.beginTransaction();
//3.动态添加Fragment
//参数1:容器id
//参数2:Fragment对象
final Fragment f2 = new Fragment2(); //需要新建一个名为Fragment2的Fragment
transaction.add(R.id.container,f2);
//4.提交事务
transaction.commit();
}
5.Fragment传值
从以下案例来了解传值
activity_tab_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".TabFragmentActivity"
android:orientation="vertical">
<!--加载Fragment的容器-->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#515151"/>
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_index"
android:text="首页"
android:drawableTop="@drawable/tab_menu_index"
style="@style/tab_menu_item"/>
<RadioButton
android:id="@+id/rb_channel"
android:text="分类"
android:drawableTop="@drawable/tab_menu_channel"
style="@style/tab_menu_item"/>
<RadioButton
android:id="@+id/rb_list"
android:text="我的学习"
android:drawableTop="@drawable/tab_menu_list"
style="@style/tab_menu_item"/>
<RadioButton
android:id="@+id/rb_me"
android:text="我"
android:drawableTop="@drawable/tab_menu_me"
style="@style/tab_menu_item"/>
</RadioGroup>
</LinearLayout>
tab_menu_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape>
<solid android:color="#FFC4C4C4"></solid>
</shape>
</item>
<item>
<shape>
<solid android:color="@android:color/transparent"></solid>
</shape>
</item>
</selector>
tab_menu_channel.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/channel_selected" android:state_checked="true"></item>
<item android:drawable="@mipmap/channel_normal"></item>
</selector>
tab_menu_index.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/index_selected" android:state_checked="true"></item>
<item android:drawable="@mipmap/index_normal"></item>
</selector>
tab_menu_list.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/list_selected" android:state_checked="true"></item>
<item android:drawable="@mipmap/list_normal"></item>
</selector>
tab_menu_me.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/me_selected" android:state_checked="true"></item>
<item android:drawable="@mipmap/me_normal"></item>
</selector>
tab_menu_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#ffffff" android:state_checked="true"/>
<item android:color="#515151"/>
</selector>
TabFragmentActivity.java
package com.example.fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class TabFragmentActivity extends AppCompatActivity implements Fragment3.MyListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_fragment);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.container, new IndexFragment());
transaction.commit();
}
public void myclick(View view){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch(view.getId()){
case R.id.rb_index:
transaction.replace(R.id.container, new IndexFragment());
break;
case R.id.rb_channel: //Activity向Fragment传值
//setArguments
//1.实例化Fragment
Fragment f1 = new Fragment1();
//2.实例化一个Bundle对象
Bundle bundle = new Bundle();
//3.存入数据到Bundle对象中
bundle.putString("msg1", "这是由Activity发往Fragment的数据");
//4.调用Fragment的setArguments方法,传入Bundle对象
f1.setArguments(bundle);
//5.添加/替换显示的Fragment
transaction.replace(R.id.container, f1);
break;
case R.id.rb_list:
transaction.replace(R.id.container, new Fragment2());
break;
case R.id.rb_me:
transaction.replace(R.id.container, new Fragment3());
break;
}
transaction.commit();
}
@Override
public void sendMsg(String msg) {
Log.e("TAG","Fragment传回的数据:"+msg);
}
}
你需要新建4个Fragment,分别为Fragment1,Fragment2,Fragment3,Fragment4
Fragment1接收值
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_1, container, false);
Bundle bundle = getArguments();
String msg1 = bundle.getString("msg1");
((TextView)v.findViewById(R.id.txt1)).setText(msg1);
return v;
}
Fragment3向Activity传值
package com.example.fragment;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment3 extends Fragment {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
//Fragment像Activity传值(接口回调)
//1.定义一个接口,在该接口中声明一个用于传递数据的方法
//2.让Activity实现该接口,然后重写回调方法,获取传入的值,然后做处理
//3.在自定义Fragment中,声明一个回调接口的引用
//4.在onAttach方法中,为第三步的引用赋值
//5.在引用调用传递数据的方法
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_3, container, false);
}
private MyListener m1;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
m1 = (MyListener) getActivity();
m1.sendMsg("消息");
}
public interface MyListener {
void sendMsg(String msg);
}
}
Activity接收值
@Override
public void sendMsg(String msg) {
Log.e("TAG","Fragment传回的数据:" + msg);
}
6.ListView
1.适配器
1.ArrayAdapter
//activity_array.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=".ArrayActivity">
<ListView
android:id="@+id/list_view1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
//ArrayActivity.java
//1.准备布局(每一项的显示效果)
//2.准备数据源
//3.实例化适配器(布局+数据源)
//4.为ListView设置适配器
public class ArrayActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_array);
ListView listView1 = findViewById(R.id.list_view1);
String[] data = {"AA","BB","CC","DD","EE","FF","GG","AA","BB","CC","DD","EE","FF","GG","AA","BB","CC","DD","EE","FF","GG","AA","BB","CC","DD","EE","FF","GG"};
//参数1:环境上下文(this)
//参数2:代表数据项所应用的布局
//参数3:数据源(数组)
//1.R.layout.item是自己写的只有文本的布局
//ArrayAdapter adapter = new ArrayAdapter(this, R.layout.item, data);
//2.android.R.layout.simple_list_item_1是android自带的只有文本的布局
//ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, data);
//3.当布局含有图片和文本的时候,可以用id指定文本
ArrayAdapter adapter = new ArrayAdapter(this, R.layout.item2, R.id.txt1, data);
listView1.setAdapter(adapter);
}
}
//item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="28sp"
android:textColor="#ff0000"/>
//item2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/txt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
2.SimpleAdapter
//activity_simple.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".SimpleActivity">
<ListView
android:id="@+id/list_view2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
//SimpleActivity.java
public class SimpleActivity extends AppCompatActivity {
private List<Map<String, Object>> data = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
//1.获取ListView对象
ListView listView2 = findViewById(R.id.list_view2);
//2.实例化适配器对象
//参数1:this
//参数2:数据源
initData();
//参数3:每一项布局
//参数4:数据来源的key数组
String[] from = {"img", "name", "mood"};
//参数5:数据去向的id数组
int[] to = {R.id.qq_img, R.id.qq_name, R.id.qq_mood};
//参数45对应索引上,from数组的元素代码数据源每个map的key,该key所替代的数据
//会作为to数组对应索引上id所代表的控件的内容显示处理
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item3, from, to);
//3.为ListView设置适配器
listView2.setAdapter(adapter);
//4.点击事件
listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//用Toast提示Name Mood
Map<String, Object> map = data.get(i);
String name = map.get("name").toString();
String mood = map.get("mood").toString();
Toast.makeText(SimpleActivity.this, name+" "+mood, Toast.LENGTH_SHORT).show();
}
});
}
private void initData() {
//左边:头像 右上:名字 右下:心情
Map<String, Object> map1 = new HashMap<>();
map1.put("img", R.mipmap.caocao);
map1.put("name", "曹操");
map1.put("mood", "宁教我负天下人,休教天下人负我");
Map<String,Object> map2 = new HashMap<>();
map2.put("img",R.mipmap.zhenji);
map2.put("name","甄姬");
map2.put("mood","飘摇兮若流风之回雪,仿佛兮若轻云之蔽月");
Map<String,Object> map3 = new HashMap<>();
map3.put("img",R.mipmap.simayi);
map3.put("name","司马懿");
map3.put("mood","无奈天命之子");
Map<String,Object> map4 = new HashMap<>();
map4.put("img",R.mipmap.guojia);
map4.put("name","郭嘉");
map4.put("mood","哦");
Map<String,Object> map5 = new HashMap<>();
map5.put("img",R.mipmap.caocao);
map5.put("name","曹操");
map5.put("mood","宁教我负天下人,休教天下人负我");
Map<String,Object> map6 = new HashMap<>();
map6.put("img",R.mipmap.zhenji);
map6.put("name","甄姬");
map6.put("mood","飘摇兮若流风之回雪,仿佛兮若轻云之蔽月");
Map<String,Object> map7 = new HashMap<>();
map7.put("img",R.mipmap.simayi);
map7.put("name","司马懿");
map7.put("mood","无奈天命之子");
Map<String,Object> map8 = new HashMap<>();
map8.put("img",R.mipmap.guojia);
map8.put("name","郭嘉");
map8.put("mood","哦");
data.add(map1);
data.add(map2);
data.add(map3);
data.add(map4);
data.add(map5);
data.add(map6);
data.add(map7);
data.add(map8);
}
}
//item3
<?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">
<ImageView
android:id="@+id/qq_img"
android:layout_width="50dp"
android:layout_height="65dp"
android:background="@mipmap/caocao"/>
<TextView
android:id="@+id/qq_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/qq_img"
android:textSize="26sp"
android:text="曹操"/>
<TextView
android:id="@+id/qq_mood"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/qq_img"
android:layout_below="@id/qq_name"
android:textColor="#00ffff"
android:text="测试数据"/>
</RelativeLayout>
3.BaseAdapter
//activity_base.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".BaseActivity">
<ListView
android:id="@+id/list_view3"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/write"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@mipmap/write"
android:layout_gravity="right|bottom"
android:layout_margin="40dp"/>
</FrameLayout>
//BaseActivity.java
public class BaseActivity extends AppCompatActivity {
private ListView listView3;
private ImageView write;
private List<Msg> list = new ArrayList<>();
private int[] ps = {R.mipmap.profile1, R.mipmap.profile2, R.mipmap.profile3, R.mipmap.profile4, R.mipmap.profile5, R.mipmap.profile6, R.mipmap.profile7, R.mipmap.profile8};
private BaseAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
listView3 = findViewById(R.id.list_view3);
write = findViewById(R.id.write);
initData();
//需要传的参数:数据源,环境
adapter = new MyAdapter(list, this);
//设置适配器
listView3.setAdapter(adapter);
write.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Msg m = new Msg(R.mipmap.profile9, "paradox", "这是动态新增的说说", false);
list.add(m);
//通知适配器更新数据
adapter.notifyDataSetChanged();
//设置listview自动显示最新数据
listView3.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
}
});
}
private void initData() {
for (int i = 1; i <= 8 ; i++) {
Msg msg = new Msg(ps[i-1], "用户"+i, "今天天气好晴朗,处处好风光"+i, i%2==0?true:false);
list.add(msg);
}
}
}
//Msg.java
public class Msg {
private int profile;
private String nickname;
private String content;
private boolean isLike;
public int getProfile() {
return profile;
}
public void setProfile(int profile) {
this.profile = profile;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public boolean isLike() {
return isLike;
}
public void setLike(boolean like) {
isLike = like;
}
public Msg(int profile, String nickname, String content, boolean isLike) {
this.profile = profile;
this.nickname = nickname;
this.content = content;
this.isLike = isLike;
}
}
//item4.xml
<?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">
<ImageView
android:id="@+id/profile"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@mipmap/profile1"
android:layout_margin="5dp"/>
<TextView
android:id="@+id/nickname"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="用户1"
android:textSize="26sp"
android:layout_toRightOf="@id/profile"
android:layout_marginTop="5dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="2048-10-24"
android:textSize="22sp"
android:layout_toRightOf="@id/profile"
android:layout_below="@id/nickname"/>
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="啊,多么有意义的日子啊!!"
android:textSize="22sp"
android:layout_below="@id/profile"/>
<ImageView
android:id="@+id/repost"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/repost"
android:layout_below="@id/content"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"/>
<ImageView
android:id="@+id/comment"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/comment"
android:layout_below="@id/content"
android:layout_toLeftOf="@id/repost"
android:layout_marginRight="10dp"/>
<ImageView
android:id="@+id/like"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/like"
android:layout_below="@id/content"
android:layout_toLeftOf="@id/comment"
android:layout_marginRight="10dp"/>
</RelativeLayout>
//MyAdapter.java
//根据准备好的数据源和子项布局完成ListView效果的一一设置
//做出一些细节处理
public class MyAdapter extends BaseAdapter {
private List<Msg> list;
private Context ctx;
public MyAdapter(List<Msg> list, Context ctx) {
this.list = list;
this.ctx = ctx;
}
//获取数量(设置ListView的长度)
@Override
public int getCount() {
return list.size();
}
//获取视图(设置ListView每一项的显示效果)-- 每个视图出现时都会执行
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = LayoutInflater.from(ctx).inflate(R.layout.item4, null);
Msg msg = list.get(i);
//头像
ImageView profile = view.findViewById(R.id.profile);
profile.setImageResource(msg.getProfile());
//昵称
TextView nickname = view.findViewById(R.id.nickname);
nickname.setText(msg.getNickname());
//内容
TextView content = view.findViewById(R.id.content);
content.setText(msg.getContent());
//是否点赞
ImageView like = view.findViewById(R.id.like);
if(msg.isLike()){
like.setImageResource(R.mipmap.liked);
}else {
like.setImageResource(R.mipmap.like);
}
//评论
ImageView comment = view.findViewById(R.id.comment);
comment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "你点击了评论", Toast.LENGTH_SHORT).show();
}
});
//转发
ImageView repost = view.findViewById(R.id.repost);
repost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "你点击了转发", Toast.LENGTH_SHORT).show();
}
});
return view;
}
//============================================================酱油方法
//获取子项
@Override
public Object getItem(int i) {
return null;
}
//获取子项id
@Override
public long getItemId(int i) {
return 0;
}
}
2.BaseAdapter案例优化
- 优化1:利用进去RecycleBin中的View,减少读view的赋值
- 优化2:通过ViewHolder避免每次getView的时候大幅度使用findViewById操作
//根据准备好的数据源和子项布局完成ListView效果的一一设置
//做出一些细节处理
public class MyAdapter extends BaseAdapter {
private List<Msg> list;
private Context ctx;
public MyAdapter(List<Msg> list, Context ctx) {
this.list = list;
this.ctx = ctx;
}
//获取数量(设置ListView的长度)
@Override
public int getCount() {
return list.size();
}
//获取视图(设置ListView每一项的显示效果)-- 每个视图出现时都会执行
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
//完成对view的设置;
//将布局资源转为view
//参数1:你所要引用的布局资源
//RecycleBin
ViewHolder holder;
if(view == null){
Log.e("TAG", "======" + i);
//优化1:利用进去RecycleBin中的View,减少读view的赋值
view = LayoutInflater.from(ctx).inflate(R.layout.item4, null);
holder = new ViewHolder();
holder.profile = view.findViewById(R.id.profile);
holder.nickname = view.findViewById(R.id.nickname);
holder.content = view.findViewById(R.id.content);
holder.like = view.findViewById(R.id.like);
holder.comment = view.findViewById(R.id.comment);
holder.repost = view.findViewById(R.id.repost);
view.setTag(holder);
}else {
//通过getTag()取出ViewHolder对象,然后能够直接通过holder.控件的方式在外面直接操作控件
//从而避免了大幅度使用findViewById操作
//而事实上,getTag()本身操作效率高
holder = (ViewHolder) view.getTag();
}
Msg msg = list.get(i);
//头像
// ImageView profile = view.findViewById(R.id.profile);
holder.profile.setImageResource(msg.getProfile());
//昵称
// TextView nickname = view.findViewById(R.id.nickname);
holder.nickname.setText(msg.getNickname());
//内容
// TextView content = view.findViewById(R.id.content);
holder.content.setText(msg.getContent());
//是否点赞
// ImageView like = view.findViewById(R.id.like);
if(msg.isLike()){
holder.like.setImageResource(R.mipmap.liked);
}else {
holder.like.setImageResource(R.mipmap.like);
}
//评论
// ImageView comment = view.findViewById(R.id.comment);
holder.comment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "你点击了评论", Toast.LENGTH_SHORT).show();
}
});
//转发
// ImageView repost = view.findViewById(R.id.repost);
holder.repost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "你点击了转发", Toast.LENGTH_SHORT).show();
}
});
return view;
}
//============================================================酱油方法
//获取子项
@Override
public Object getItem(int i) {
return null;
}
//获取子项id
@Override
public long getItemId(int i) {
return 0;
}
//1.自定义一个类,叫做ViewHolder
//2.将需要保存的视图声明为公开的属性
//3.什么时候保存?当view为null时,完成对ViewHolder的示例化工作,并未各个空间属性赋值
//4.什么时候用?什么时候都要用(性能提升是在view补位null时体现,滚动ListView时体现)
//5.怎么用?当view为null时,完成了ViewHolder及内部控件属性的初始化工作后,调用一句代码
//view.setTag(holder)
//当view不为null时,holder = view.getTag();
static class ViewHolder {
public ImageView profile,like,comment,repost;
public TextView nickname, content;
}
}