布局
Android提供了大量的布局
Android中的Layout其实也是一个视图,它们是一些视图容器,都继承了ViewGroup这个抽象类,这是一个容器视图类,这个类继承了View类。
布局参数
Android中每种布局都有一个对应的布局参数LayoutParams。
线性布局
在线性布局中,所有控件按照排列方式依次排列。默认情况下,所有控件按照水平排列方式依次排列。可以通过setOrientation方法设置排列方式,即排列方向。如果指定为LinearLayout.VERTICAL,按照垂直排列方向依次排列。水平排列方式为LinearLayout.HORIZONTAL。
LinearLayout
在Android Studio下,有时候会遇到这种错误提示:“No orientation specified, and the default is horizontal. This is a common source of bugs when children are added dynamically.”
出现这种错误提示的原因是我们在编写布局文件时,我们编写了一个空的LinearLayout布局,如下,里边没有放置任何子视图,我们可能希望在代码中动态的添加子视图,对于这种情况,我们需要指定android:orientation参数显式的设置一个线性排列方向,如android:orientation="horizontal",或者android:orientation="vertical"。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linear" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff"> </LinearLayout>
LinearLayoutCompat
ForegroundLinearLayout
相对布局
Android提供RelativeLayout相对布局。
RelativeLayout
android:layout_alignParentTop
android:layout_alignParentBottom
android:layout_alignParentLeft
android:layout_alignParentRight
在下面的布局例子中,布局中显示一个ImageView,并在布局的左上角显示一个TextView,在布局的右上角显示一个CheckBox。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#ffffff" android:id="@+id/item" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="300px" android:textSize="18sp" android:scaleType="centerCrop"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:background="@android:color/transparent" android:textSize="18sp" android:gravity="center" android:text=" "/> <CheckBox android:id="@+id/radio_select_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:scaleX="0.8" android:scaleY="0.8" android:button="@null" android:background="@drawable/check_style"/> </RelativeLayout>
FlowLayout
GridLayout
GridLayout是一种网格布局,或者说表格布局。
GridLayout.LayoutParams
通过两个Spec参数来构造网格布局参数,一个是行规格,一个是列规格。
public LayoutParams(Spec rowSpec, Spec columnSpec) { this(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, rowSpec, columnSpec); }
默认构造网格布局参数的方法
public LayoutParams() { this(Spec.UNDEFINED, Spec.UNDEFINED); }
通过另一个ViewGroup.LayoutParams布局参数来构造网格布局参数
public LayoutParams(ViewGroup.LayoutParams params) { super(params); }
通过另一个MarginLayoutParams布局参数来构造网格布局参数
public LayoutParams(MarginLayoutParams params) { super(params); }
通过另一个LayoutParams布局参数来构造网格布局参数
public LayoutParams(LayoutParams source) { super(source); this.rowSpec = source.rowSpec; this.columnSpec = source.columnSpec; }
通过上下文和属性集来构造网格布局参数
public LayoutParams(Context context, AttributeSet attrs) { super(context, attrs); reInitSuper(context, attrs); init(context, attrs); }
GridLayout grid = view.findViewById(R.id.grid);
grid.setOrientation(GridLayout.HORIZONTAL);
grid.setColumnCount(4);
grid.setRowCount(5);
向GridLayout中添加子视图
for (int i = 0; i < 16; i++) {
ImageView itemView = new ImageView(parent.getContext());
itemView.setBackgroundColor(Color.RED);
itemView.setImageResource(R.drawable.photo);
itemView.setPadding(2, 0, 2, 0);
itemView.setTag("useralbum");
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemSelectedListener.onItemSelected(v);
}
});
GridLayout.LayoutParams itemViewLayoutParams =
new GridLayout.LayoutParams(
GridLayout.spec(GridLayout.UNDEFINED, 1f),
GridLayout.spec(GridLayout.UNDEFINED, 1f));
itemView.setLayoutParams(itemViewLayoutParams);
grid.addView(itemView);
}
ConstraintLayout
CoordinatorLayout
FrameLayout
在调用FragmentContainerView的addView(@NonNull View child, int index, @Nullable ViewGroup.LayoutParams params)方法(这个方法继承至ViewGroup类)的时候,报了一个错误:IllegalStateException,提示java.lang.IllegalStateException: Views added to a FragmentContainerView must be associated with a Fragment. View app.at.NoScrollListView{d7ce44c V.ED.VC.. ......I. 0,0-0,0} is not associated with a Fragment.信息。
FragmentContainerView的这个addView方法(这个方法继承至ViewGroup类)会调用到FragmentContainerView的addView(@NonNull View child, int index, @Nullable ViewGroup.LayoutParams params)方法,其中有这么一段检查:
if (FragmentManager.getViewFragment(child) == null) { throw new IllegalStateException("Views added to a FragmentContainerView must be" + " associated with a Fragment. View " + child + " is not associated with a" + " Fragment."); }
这里FragmentManager的getViewFragment方法如下:
@Nullable static Fragment getViewFragment(@NonNull View view) { Object tag = view.getTag(R.id.fragment_container_view_tag); if (tag instanceof Fragment) { return (Fragment) tag; } return null; }
这里会检查加入的view的一个key为R.id.fragment_container_view_tag的tag,这个tag必须是一个Fragment实例。
不过我们在代码中不能直接使用R.id.fragment_container_view_tag这个id。
在调用FragmentTransaction的add(@IdRes int containerViewId,@NonNull androidx.fragment.app.Fragment fragment)方法的时候,报了一个错误:IllegalStateException,提示java.lang.IllegalArgumentException: Can't add fragment Fragment{ea2c505} (b905f807-04f2-4679-8a74-9b8d72b53151) with tag null to container view with no id信息
FragmentTransaction的这个add方法会调用到FragmentTransaction的doAddOp方法,其中有这么一段检查:
if (containerViewId == View.NO_ID) { throw new IllegalArgumentException("Can't add fragment " + fragment + " with tag " + tag + " to container view with no id"); }
即这里的FragmentContainerView必须要指定一个id,或者如果这个FragmentContainerView是在代码中直接创建的话,需要调用setId方法指定一个id,如fragmentContainerView.setId(R.id.fragment_container_view)。
在调用FragmentTransaction的add(@IdRes int containerViewId,@NonNull androidx.fragment.app.Fragment fragment)方法的时候,报了一个错误:IllegalStateException,提示java.lang.IllegalStateException: Fragment must be a public static class to be properly recreated from instance state.信息
FragmentTransaction的这个add方法会调用到FragmentTransaction的doAddOp方法,其中有这么一段检查:
final Class<?> fragmentClass = fragment.getClass(); final int modifiers = fragmentClass.getModifiers(); if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers) || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) { throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName() + " must be a public static class to be properly recreated from" + " instance state."); }
即传入的这个Fragment对象类必须满足:
1、不可以是匿名类
2、必须是public类
3、必须是静态类或者成员类
ScrimInsetsFrameLayout
ContentFrameLayout
TabLayout
TextInputLayout
DrawerLayout
FitWindowsLinearLayout
FitWindowsFrameLayout
ButtonBarLayout
BaselineLayout
AppBarLayout
ActionBarOverlayLayout
CollapsingToolbarLayout
CircularRevealLinearLayout
CircularRevealRelativeLayout
CircularRevealGridLayout
CircularRevealFrameLayout
CircularRevealCoordinatorLayout
SnackbarLayout
SnackbarContentLayout
SnackbarBaseLayout
AlertDialogLayout
MotionLayout
布局管理
布局管理器
布局参数
选项卡
Android提供了多种视图组件来实现选项卡。
TabLayout
TabRippleColor
默认情况下,点击选择一个选项时,会有波纹效果。
如果想要去掉这个效果的话,可以设置为null。
tabLayout.setTabRippleColor(null);
SelectedTabIndicator
TabLayout当前选项下面有一条下划线的指示效果,这个效果就是一个Indicator,也称为selection indicator,默认情况下就是选项卡下面有一条下划线。这个Indicator是一个Drawable,可以看TabLayout的Drawable tabSelectedIndicator。这个Indicator也是有高的。
tabLayout.setSelectedTabIndicator(R.drawable.tab_indicator);
在res/drawable下新建一个tab_indicator.xml文件
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:width="6dp" android:height="6dp" android:gravity="center" android:bottom="6dp"> <shape> <corners android:radius="3dp"/> </shape> </item> </layer-list>
这里我们想让Indicator水平居中,但如果设置为android:gravity="center_horizontal"的话,又没有效果,Indicator都显示不出来。设置为android:gravity="center"是可以的,它可以让Indicator水平垂直都居中,不过Indicator只显示了上面一半,下面一半没有显示出来,垂直居中感觉是以底部为基准进行垂直居中。这里设置android:bottom="6dp",在底部留出相应的内边界空间。
还有一种写法
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:gravity="center" android:bottom="6dp"> <shape android:shape="rectangle"> <solid android:color="@color/green"/> <corners android:bottomLeftRadius="3dp" android:bottomRightRadius="3dp" android:topLeftRadius="3dp" android:topRightRadius="3dp"/> <size android:height="6dp" android:width="6dp"/> </shape> </item> </layer-list>
例子
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:width="20dp" android:height="5dp" android:gravity="center" android:bottom="5dp"> <shape> <corners android:radius="5dp" /> </shape> </item> </layer-list>
尝试设置Indicator为一个图标是没有效果的。
tabLayout.setSelectedTabIndicator(R.drawable.toolbar_selected_normal);
可能反而去掉了默认的下划线指示效果。
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:width="20dp" android:height="20dp" android:gravity="center" android:drawable="@drawable/toolbar_selected_normal" android:bottom="20dp"> <shape/> </item> </layer-list>
有时候我们不想要有这个指示效果,想要去掉这条下划线。
可以通过setSelectedTabIndicator设置这个Indicator,如果指定为null,就不会有这个了。也可以将Indicator的高设置为0。调用setSelectedTabIndicatorHeight方法可以指定高。
长按事件
tabLayout.getTabAt(0).view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { Log.d(getClass().getName(), "long click"); return true; } });
相关推荐
使用合适的布局方法(不用约束布局),实现如下界面。并实软件国际化,当汉语人群使用软件时,呈现左下界面,而英语人群使用软件时,呈现右下界面。Android项目开发。
百分比布局<android.support.percent.PercentLinearLayout android:id="@+id/tv_solid_number_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft=...
Android布局文件的属性值解析说明: 1 android:id [为控件指定相应的ID] 2 android:text [指定控件当中显示的文字 需要注意的是 这里尽量使用strings xml文件当中的字符串] 3 android:gravity [指定View组件的对齐...
安卓布局讲解。各个控件的讲解,及其属性。代码展示。 1 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" 4 android:layout_width="fill_parent" 5...
【android】通过父容器大小,子控件百分比布局 导入项目添加依赖,可以直接复制源码进项目; 1、在自己布局文件中,最外层容器添加引用 xmlns:badboy="http://schemas.android.com/apk/res-auto" badboy自己随意...
要在主工程的gradle中添加版本信息或者自己在资源包中添加版本号,依赖此资源就可以实现FlexboxLayout与Recycleview的后续操作,我的主工程版本代码: ext { minSdkVersion = 9 targetSdkVersion = 25 ...
Android 开发 (实验五) 实验题目:Android 组件布局试验 指导老师: 班 级:计算机科学与技术系班 姓 名: 一、实验目的 1、掌握 Android 组件布局的使用方法 2、学会组件布局的重要属性与应用 3、能够根据需求,...
android布局和控件 LinearLayout:线性布局,从左到右 第一种方法实现界面布局:手动写布局 第二种方法实现界面布局:布局文件(layout中的activty_main.xml) 其实就是标签的嵌套,注意单标签、双标签 拨打电话的...
Android布局中的 android:onClick=“…”属性设置点击时从上下文中调用指定的方法。该属性值和要调用的方法名称完全一致。一般在Activity定义符合如下参数和返回值的函数并将方法名字符串指定为该属性值即可: ...
Android 相对布局实例 ,RalateLayout
Android中使用RelativeLayout完成梅花布局的代码清单.pdf 学习资料 复习资料 教学资源
Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件。 帧布局(FrameLayout):组件从屏幕左上方布局组件。 表格布局(TableLayout):按照行列方式布局组件。 ...
Android xml布局文件工具
android:layout_width="fill_parent" android:layout_height="fill_parent"> <!-- FrameLayout - 层叠式布局。以左上角为起点,将 FrameLayout 内的元素一层覆盖一层地显示 --> <FrameLayout android...
介绍Android五中布局的一个示例代码.
-- 在主布局添加文本框和密码框 --> <TextView android:text = "@string/password" android:layout_width="match_parent" android:layout_height="wrap_content"/> <EditText android:id="@+id/password" android:...
android实验界面设计:布局管理器.doc
-- 在主布局添加文本框和密码框 --> <TextView android:text = "@string/password" android:layout_width="match_parent" android:layout_height="wrap_content"/> <EditText android:id="@+id/password" android:...
首先,在res下面新建一个文件夹drawable,在drawable下面新建三个xml文件:shape_corner_down.xml、shape_corner_up.xml和shape_corner.xml,分别是下面两个角是圆角边框,上面两个角是圆角...solid android:color=#0
Android流式布局简单实现,通过继承ViewGroup,重写OnLayout方法,实现标签的流式布局