有些东西,一直忽略了它们,因为它们是空气
现在发现,它们很重要,因为它们是空气
嘿嘿,文艺一把
安卓5大布局:LinearLayout、FrameLayout、TableLayout、RelativeLayout、AbsoluteLayout
老生常谈的东西,这个时代也可以称为LinearLayout、RelativeLayout时代
后面出现了PercentLayout,最近几年又出现了ConstraintLayout
为什么会这样演化,ConstraintLayout又有什么优势?
一、LinearLayout优化
常用的include,布局复用。项目中一些View多次被引用就出现了这个方案
include虽然好用,可是容易造成一些多余的层级结构,然后诞生了merge,合并融合。
merge需要注意:
1、<merge /> must be the root element(必须是根元素)。
2、LayoutInflater.from(context()).inflate(int resource,ViewGroup root,boolean attachToRoot)中resource为根节点merge的xml布局时,必须指定root,和attachToRoot为true
二、LinearLayout与RelativeLayout 性能区别
LinearLayout用起来很舒服,方方正正的。但是有些需求,会造成嵌套嵌套再嵌套
RelativeLayout可以让我们减少一点嵌套,既减少一些布局层次结构
大体来说,相对于层次相同的布局,LinearLayout性能是高于RelativeLayout的。因为RelativeLayout可能存在参照物,所以会对子View做两次measure,横向、纵向各一次。
RelativeLayout是为了让我们减少布局层次,从而提高性能
三、PercentLayout
PercentLayout接触不多。适配是安卓很让人头疼的问题。每次这个时候我都很羡慕前端网页的百分比布局,不要太爽
虽然LinearLayout有比重,但是不适用很多场景
四、ConstraintLayout
不止ios有约束布局了。
ConstraintLayout的推出,个人觉得google的宗旨很明确:减少布局层次,提高性能
它有LinearLayout的比重、有PercentLayout的百分比、是升级版的RelativeLayout
具体属性,用法自行百度
ConstraintLayout使用中,需要动态修改布局时,习惯找LayoutParams。然后发现ConstraintSet
多处理细节,APP性能的提升会让人大吃一惊
ConstraintSet很舒服,最后贴个简单的demo,看看
简单的tab切换。间距等分、下标跟随标题长度、选中标题变大
可以自己封装成列表+适配器,也可以跟viewpage关联起来
布局代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/parent_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_20">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_24"
android:gravity="center_vertical"
android:text="卖商品"
android:textColor="@color/gray_6d7074"
android:textSize="@dimen/dp_15"
app:layout_constraintLeft_toLeftOf="parent"/>
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="支付"
android:textColor="@color/gray_6d7074"
android:textSize="@dimen/dp_15"
app:layout_constraintBaseline_toBaselineOf="@+id/tv1"
app:layout_constraintLeft_toRightOf="@+id/tv1"/>
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="测试"
android:textColor="@color/gray_6d7074"
android:textSize="@dimen/dp_15"
app:layout_constraintBaseline_toBaselineOf="@+id/tv2"
app:layout_constraintLeft_toRightOf="@+id/tv2"/>
<TextView
android:id="@+id/tv4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="你咬我啊"
android:textColor="@color/gray_6d7074"
android:textSize="@dimen/dp_19"
app:layout_constraintBaseline_toBaselineOf="@+id/tv3"
app:layout_constraintLeft_toRightOf="@+id/tv3"/>
<TextView
android:id="@+id/tv5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="开心"
android:textColor="@color/gray_6d7074"
android:textSize="@dimen/dp_15"
app:layout_constraintBaseline_toBaselineOf="@+id/tv4"
app:layout_constraintLeft_toRightOf="@+id/tv4"/>
<LinearLayout
android:id="@+id/lin_bg"
android:layout_width="0dp"
android:layout_height="@dimen/dp_7"
android:background="#ff103663"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="@+id/tv5"
app:layout_constraintStart_toEndOf="@+id/tv5"
app:layout_constraintStart_toStartOf="@+id/tv5"
app:layout_constraintTop_toBottomOf="@+id/tv5">
<View
android:layout_width="fill_parent"
android:layout_height="@dimen/dp_2"
android:layout_marginTop="@dimen/dp_4"
android:background="#ffffff"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
java代码
import android.content.Context
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.constraint.ConstraintLayout
import android.support.constraint.ConstraintSet
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.widget.TextView
class MainActivity2 : AppCompatActivity(), View.OnClickListener {
private var parentLayout: ConstraintLayout? = null
private var tv1: TextView? = null
private var tv2: TextView? = null
private var tv3: TextView? = null
private var tv4: TextView? = null
private var tv5: TextView? = null
companion object {
fun startActivity(context: Context) {
context.startActivity(Intent(context, MainActivity2::class.java))
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
parentLayout = findViewById(R.id.parent_layout)
tv1 = findViewById(R.id.tv1)
tv2 = findViewById(R.id.tv2)
tv3 = findViewById(R.id.tv3)
tv4 = findViewById(R.id.tv4)
tv5 = findViewById(R.id.tv5)
tv1?.setOnClickListener(this)
tv2?.setOnClickListener(this)
tv3?.setOnClickListener(this)
tv4?.setOnClickListener(this)
tv5?.setOnClickListener(this)
initTitleData()
changeView(1)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.tv1 -> {
changeView(0)
}
R.id.tv2 -> {
changeView(1)
}
R.id.tv3 -> {
changeView(2)
}
R.id.tv4 -> {
changeView(3)
}
R.id.tv5 -> {
changeView(4)
}
}
}
//二级标题列表
private val fontTextList = ArrayList<TextView>()
internal var set: ConstraintSet? = null
private var widthCount = 0
private var leftMargin: Int = 0
private fun initTitleData() {
fontTextList.add(tv1!!)
fontTextList.add(tv2!!)
fontTextList.add(tv3!!)
fontTextList.add(tv4!!)
fontTextList.add(tv5!!)
set = ConstraintSet()
widthCount = 0
leftMargin = this.resources.getDimensionPixelSize(R.dimen.dp_48)
for (view in fontTextList) {
val w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
val h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
view.measure(w, h)
val width = view.measuredWidth
widthCount += width
Log.e("view width", width.toString())
}
Log.e("view widthCount", widthCount.toString() + "")
val dm = DisplayMetrics()
this.windowManager.defaultDisplay.getMetrics(dm)
val screenWidth = dm.widthPixels
Log.e("屏幕宽度", screenWidth.toString() + "")
val paddWidth = screenWidth - (widthCount + leftMargin)
if (paddWidth <= 0) {
return
}
val viewMargin = paddWidth / (fontTextList.size - 1)
Log.e("单个view的间距", viewMargin.toString())
for (i in fontTextList.indices) {
if (i != 0) {
val topView = fontTextList[i - 1]
val currentView = fontTextList[i]
set!!.clone(parentLayout)
set!!.connect(currentView.id, ConstraintSet.START, topView.id, ConstraintSet.END, viewMargin)
set!!.applyTo(parentLayout)
Log.e("单个view的间距$i", viewMargin.toString())
}
}
}
//刷新view
private fun changeView(index: Int) {
for (i in fontTextList.indices) {
fontTextList[i].setTextSize(
android.util.TypedValue.COMPLEX_UNIT_PX,
resources.getDimensionPixelOffset(R.dimen.sp_15).toFloat()
)
fontTextList[i].setTextColor(resources.getColor(R.color.gray_6d7074))//#6d7074
if (i == index) {
fontTextList[i].setTextSize(
android.util.TypedValue.COMPLEX_UNIT_PX,
resources.getDimensionPixelOffset(R.dimen.sp_19).toFloat()
)
fontTextList[i].setTextColor(resources.getColor(R.color.blue_ff103663))//#ff103663
}
}
set?.clone(parentLayout)
set?.connect(R.id.lin_bg, ConstraintSet.START, fontTextList[index].id, ConstraintSet.START, 0)
set?.connect(R.id.lin_bg, ConstraintSet.END, fontTextList[index].id, ConstraintSet.END, 0)
set?.applyTo(parentLayout)
}
}