ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android笔记(二)

2022-02-03 12:03:18  阅读:203  来源: 互联网

标签:控件 val 布局 笔记 fruit Android View view


Android笔记(二)

文章目录

1. 基础UI

1.1 常用控件

关于单位:

  • dp:一般用于固定值的单位,可以保证在不同分辨率显示效果大致相同
  • sp:用于文字大小的单位,保证程序中文字大小可以随系统文字尺寸变化

注:下面每个控件后的属性只代表《第三行代码》中在该控件小节中学习到的,控件属性一般都能应用在大部分的控件中

TextView:

  • android:gravity属性指定文字对齐方式(gravity:重力),可选值top、bottom、start、end、center等,通过|来指定多个值

Button:……

EditText:

  • android:hint属性指定一段提示性的文本
  • android:maxLines属性指定EditText最大行数

ImageView:

  • android:src属性指定所需资源,一般图片资源存储在drawable-xxx目录中,一般主流的手机屏幕分辨率是xxhdpi的
  • 可以通过imageView.setImageResource()方法动态更改图片

ProgressBar:(progress:进步)

  • android:visibility属性指定控件的可见性,可选值visible 默认,可见、invisible “透明”、gone 完全不可见,也可以通过控件的setVisibility()方法动态更改可见性,可传入参数View.VISIBLE、View.INVISIBLE、View.GONE
  • style属性设置为水平进度条(?android:attr/progressBarStyleHorizontal),默认圆形进度条
  • android:max属性设置进度条最大值
class MainActivity : AppCompatActivity(), View.OnClickListener {
    ...
    override fun onClick(v: View?) {
        when(v?.id) {
            R.id.button -> {
                progressBar.progress = progressBar.progress + 10
            }
        }
    }
}

AlertDialog:

class MainActivity : AppCompatActivity(), View.OnClickListener {
    ...
    override fun onClick(v: View?) {
        when(v?.id) {
            R.id.button -> {
                AlertDialog.Builder(this).apply {
                    setTitle(This is Dialog)
                    // setView(R.layout.dialog) 给弹窗设置自定义的布局
                    setMessage("Something important.")
                    // positive:积极的 negative:消极的,负
                    setPositiveButton("OK") { dialog, which -> }
                    setNegativeButton("Canel") { dialog, which -> }
                    show()
                }
            }
        }
    }
}

1.2 基本布局

LinearLayout线性布局:

  • android:orientation属性指定排列方向,可选值vertical(垂直)、horizontal(水平)
  • android:layout_gravity属性用于指定控件在布局中的对齐方式,可选值与gravity差不多
  • android:weight属性根据比例来指定控件大小,由这个属性决定的方向属性规范设为0dp

RelativeLayout相对布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:Layout_height="match_parent">
	<!-- align:对齐 -->
    <Button
		android:id="@+id/buttonl"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentLeft="true"
		android:layout_alignParentTop="true"
		android:text="Button l" />
    <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/buttonl"
		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:texte"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>

FrameLayout帧布局:

所有控件默认摆放在布局左上角,主要在用到Fragment的时候使用

1.3 自定义控件

控件继承关系:

View TextView ImageView ViewGroup EditText Button LinearLayout RelativeLayout ...

View基础UI组件,在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件

ViewGroup可以包含多个子View和子ViewGroup,用于放置控件和布局的容器

引入布局:

  • 自定义一个xml布局
  • 然后在主布局中通过<include>标签的layout属性引入布局

创建自定义控件:

使引入的布局中的一些控件可以响应事件

例:自定义导航栏

class TitleLayout(context: Context, attrs: AttributeSet) : 
	LinearLayout(context, attrs) {
    // attribute:属性
    init {
        LayoutInflater.from(context).inflate(R.layout.title, this)
        titleBack.setOnClickListener {
            val activity = context as Activity
            activity.finish()
        }
    }
}

Kotlin小知识——as关键字用于强制类型转换

<!-- 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>

相关知识:

AlertDialog(对话框)详解 - 菜鸟教程

RelativeLayout(相对布局)- 菜鸟教程

从inflate方法开始,搞懂LayoutInflater的inflate过程(上) - 知乎

2. ListView和RecyclerView

2.1 ListView基本使用

简单使用:……

定制界面:

定制一个界面,一个ImageView显示水果图片和一个TextView显示水果名称

// 定义实体类,作为ListView适配器的适配类型
class Fruit(val name: String, val imageId: Int)
// 自定义适配器
class FruitAdapter(activity: Activity, val resourceId: Int, data: List<Fruit>) : 
	ArrayAdapter<Fruit>(activity, resourceId, data) {
    // getView()方法在每个子项被滚动到屏幕内的时候会被调用
	override fun getView(position: Int, convertView: View?, parent: ViewGoup): View {
        val view = LayoutInflater.from(context).inflate(resourced, parent. false)
        val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
        val fruitName: TextView = view.findViewById(R.id.fruitName)
        val fruit = getItem(position)	// 获取当前像的Fruit实例
        if (fruit != null) {
            fruitImage.setImageResource(fruit.imageId)
            fruitImage.text = fruit.name
        }
        return view
    }
}

然后在Activity中设置这个自定义的适配器就行

提升运行效率

效率低:自定义适配器的getView()方法每次都将布局重新加载一遍,ListView快速滚动的时候,会成为性能的瓶颈

解决:缓存之前的一些资源

class FruitAdapter(activity: Activity, val resourceId: Int, data: List<Fruit>) : 
	ArrayAdapter<Fruit>(activity, resourceId, data) {
        
    // ViewHolder内部类对控件实例进行缓存
    inner class ViewHolder(val fruitImage: ImageView, val fruitName: TextView)
    
	override fun getView(position: Int, convertView: View?, parent: ViewGoup): View {
        // convertView用于将之前加载好的布局进行缓存(convert:转换)
        val view: View
        val viewHodler: ViewHolder
        
        if (convertView == null) {
            val view = LayoutInflater.from(context).inflate(resourced, parent. false)
            val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
        	val fruitName: TextView = view.findViewById(R.id.fruitName)
            viewHolder = ViewHolder(fruitImage, fruitName)
            view.tag = ViewHolder
        } else {
            view = convertView
            viewHodler = view.tag as ViewHolder
        }
        
        
        val fruit = getItem(position)
        if (fruit != null) {
            viewHodler.fruitImage.setImageResource(fruit.imageId)
            viewHodler.fruitImage.text = fruit.name
        }
        return view
    }
}

ListView点击事件:

listView.setOnItemClickListener { parent, view, position, id -> 
	val fruit = fruitList[position]
    Toast.makeText(this, fruit.name, Toast.LENGTH_SHORT).show()
}

Kotlin小知识——Lambda表达式没有用到的参数可以使用下划线替代,但相对位置不能改变

2. RecyclerView

ListView性能差,不能实现数据横向滚动,RecyclerView优化了这些问题

基本用法

使用RecyclerView需要在build.grale文件的dependencies闭包中添加implementation 'androidx.recyclerview:recyclerview:1.0.0'

// 新建一个FruitAdapter类继承自RecyclerView.Adapter
class FruitAdpater(val fruistList: List<Fruit>) : 
	RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
	
	inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        // view是子项最外层布局
        val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
        val fruitName: TextView = view.findViewById(R.id.fruitName)
    }
    // 用于创建ViewHolder实例
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHodler {
        val view = LayoutInflater.from(parent.context)
        .inflate(R.layout.fruit_item, parent, false)
        return ViewHolder(view)
    }
    // 用于对子项的数据进行赋值
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val fruit = fruitList[position]
        holder.fruitImage.setImageResource(fruit.imageId)
        holder.fruitName.text = fruit.name
    }
        
   	override fun getItemCount() = fruitList.size
}

// 使用RecyclerView
class MainActivity : AppCompatActivity() {
    private val fruitList = ArrayList<Fruit>()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        initFruit()
        // layoutManager用于指定RecyclerView布局方式
        val layoutManager = LinearLayoutManager(this)
        recycleView.layoutManager = layoutManager
        val adapter = FruitAdapter(fruitList)
        recyclerView.adapter = adapter
    }
    ...
}

横向滚动:

通过LinearLayoutManager的方法setOrientaton()设置值为LinearLayoutManager.HORIZONTAL

也就是上述代码中增加一行layoutManager.orientaton = LinearLayoutManager.HORIZONTAL

ListView的布局排列时自身管理的,而RecyclerView是交给了LayoutManager。LayoutManager指定了一套可扩展的布局排列接口,子类只要按照接口规范实现就能指定各种不同排列方式的布局,提供了LinearLayoutManager、GridLayoutManager(网格布局)和StaggeredGridLayoutManager(瀑布流布局)

瀑布流布局:

class MainActivity : AppCompatActivity() {
	private val fruitList = ArrayList<Fruit>()
	override fun onCreate(savedInstancestate: Bundle?)
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)
		initFruits() // 初始化水果数据
    	// 第一个参数:指定布局列数
    	// 第二个参数:VERTICAL表示让布局纵向排列
		val layoutManager = StaggeredGridLayoutManager(3,
		StaggeredGridLayoutManager.VERTICAL)
		recyclerview.layoutManager = layoutManager
		val adapter = FruitAdapter(fruitList)
		recyclerview.adapter = adapter
	}
}

RecyclerView点击事件:

与ListView不同,RecyclerView没有类似setOnItemClickListener()这样的方法,而是需要给子项具体的View去注册点击事件,可能会复杂一点,但这样的好处可以去处理布局中具体的View,而ListVi额外要实现的话会有点麻烦

class FruitAdapter(val fruitList:List<Fruit>) :
	RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
    ...
	override fun onCreateviewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
		val view = LayoutInflater.from(parent.context)
		.inflate(R.layout.fruit item, parent, false)
		val viewHolder = ViewHolder(view)
        // 给子项注册点击事件
		viewHolder.itemview.setOnCLickListener {
			val position = viewHoLder.adapterPosition
			val fruit = fruitList[position]
			Toast.makeText(parent.context, "you clicked view ${fruit.name}",Toast.LENGTH_SHORT).show()
		}
        // 给子项中的图片设置点击事件
		viewHolder.fruitImage.setOnCLickListener {
			val position = viewHolder.adapterPosition
			val fruit = fruitList[position]
			Toast.makeText(parent.context, "you clicked image ${fruit.name}",Toast.LENGTH_SHORT).show()
        }
	return viewHolder
    }
    ...
}

相关知识:

Adapter基础讲解 - 菜鸟教程

创建可调整大小的位图(9-Patch 文件) - Android 开发者

标签:控件,val,布局,笔记,fruit,Android,View,view
来源: https://blog.csdn.net/Vis_jerome/article/details/122774894

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有