android自定义抽屉布局,Android 沉浸式DrawerLayout(抽屉布局)案例

演示

5ae3d9555853?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

device-2018-07-23-211847.gif

https://github.com/Mr-Cai/Drawer

实现步骤

布局文件

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#0ff"

android:gravity="center"

android:text="@string/app_name"

android:textColor="#fff"

android:textSize="50sp" />

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_gravity="start"

android:background="@color/colorPrimary"

android:fitsSystemWindows="true"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="@string/lift_menu" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/a" />

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_gravity="end"

android:background="@color/colorAccent"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center"

android:text="@string/right_menu"

android:textColor="#fff" />

沉浸式配置

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

window.statusBarColor = Color.TRANSPARENT

}

圆角图片

自定义圆角属性

kotlin文件

package com.example.m.draw

import android.content.Context

import android.graphics.*

import android.graphics.drawable.BitmapDrawable

import android.graphics.drawable.Drawable

import android.os.Bundle

import android.os.Parcelable

import android.support.v7.widget.AppCompatImageView

import android.util.AttributeSet

import android.util.TypedValue

import android.util.TypedValue.COMPLEX_UNIT_DIP

class RoundImage(context: Context, attrs: AttributeSet) : AppCompatImageView(context, attrs) {

private var mImgType: Int = 0//图片类型

private var mBorderRadius: Int = 0//圆角大小

private val mBitmapPaint: Paint = Paint()//绘图画笔

private var mRadius: Int = 0//圆角半径

private val mMatrix: Matrix = Matrix()//缩放3x3矩阵

private var mBitmapShader: BitmapShader? = null//渲染图像颜色

private var mWidth: Int = 0//图像宽度

private var mRoundRect: RectF? = null//圆角矩形

companion object {

const val TYPE_CIRCLE = 0//圆形图片

const val TYPE_ROUND = 1//圆角图片

const val BORDER_RADIUS_DEFAULT = 10//圆角图片

const val STATE_INSTANCE = "STATE_INSTANCE"

const val STATE_TYPE = "STATE_TYPE"

const val STATE_BORDER_RADIUS = "STATE_BORDER_RADIUS"

}

init {

mBitmapPaint.isAntiAlias = true

val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImage)

mBorderRadius = typedArray.getDimensionPixelSize(R.styleable.RoundImage_borderRadius,

TypedValue.applyDimension(COMPLEX_UNIT_DIP, BORDER_RADIUS_DEFAULT.toFloat(),

resources.displayMetrics).toInt())

mImgType = typedArray.getInt(R.styleable.RoundImage_type, TYPE_CIRCLE)//默认圆形图片

typedArray.recycle()

}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec)

if (mImgType == TYPE_CIRCLE) {//如果改变图片类型为圆形,则强制图片宽高一致

mWidth = Math.min(measuredWidth, measuredHeight)

mRadius = mWidth / 2

setMeasuredDimension(mWidth, mWidth)

}

}

private fun setUpShader() {//设置渲染着色

val drawable = drawable ?: return

val bitmap = drawableToBitmap(drawable)//指定区域内绘制着色的位图

mBitmapShader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)

var scale = 1.0f

if (mImgType == TYPE_CIRCLE) {

val bitmapSize = Math.min(bitmap.width, bitmap.height)

scale = mWidth * 1.0f / bitmapSize

} else if (mImgType == TYPE_ROUND) {//如果图片宽高与自定义控件宽高不匹配,则计算缩放比例

scale = Math.max(width * 1.0f / bitmap.width,

height * 1.0f / bitmap.height)

}

mMatrix.setScale(scale, scale)//缩放矩阵

mBitmapShader!!.setLocalMatrix(mMatrix)//变换矩阵

mBitmapPaint.shader = mBitmapShader//设置渲染器

}

private fun drawableToBitmap(drawable: Drawable): Bitmap {

if (drawable is BitmapDrawable) {

return drawable.bitmap

}

val width = drawable.intrinsicWidth

val height = drawable.intrinsicHeight

val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)

val canvas = Canvas(bitmap)

drawable.setBounds(0, 0, width, height)

drawable.draw(canvas)

return bitmap

}

override fun onDraw(canvas: Canvas) {

setUpShader()

if (mImgType == TYPE_CIRCLE) {

canvas.drawCircle(mRadius.toFloat(), mRadius.toFloat(),

mRadius.toFloat(), mBitmapPaint)

} else {

canvas.drawRoundRect(mRoundRect, mBorderRadius.toFloat(),

mBorderRadius.toFloat(), mBitmapPaint)

}

}

override fun onSizeChanged(w: Int, h: Int, oldW: Int, oldH: Int) {

super.onSizeChanged(w, h, oldW, oldH)

if (mImgType == TYPE_ROUND) {

mRoundRect = RectF(0f, 0f, width.toFloat(), height.toFloat())

}

}

override fun onSaveInstanceState(): Parcelable? {

val bundle = Bundle()

bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState())

bundle.putInt(STATE_TYPE, mImgType)

bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius)

return bundle

}

override fun onRestoreInstanceState(state: Parcelable) {

if (state is Bundle) {

super.onRestoreInstanceState(state.getParcelable(STATE_INSTANCE))

mImgType = state.getInt(STATE_TYPE)

mBorderRadius = state.getInt(STATE_BORDER_RADIUS)

} else {

super.onRestoreInstanceState(state)

}

}

}

坑点:

正常情况下,沉浸状态下状态栏是透明的,和布局融为一体,且布局内容和状态栏有界限.

现在将fitSystemWindow(贴合窗口)属性写在根布局就造成了灰色状态栏

5ae3d9555853?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

图片.png

layout_gravity属性未设置,造成抽屉覆盖主页面

5ae3d9555853?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

device-2018-07-23-214104.png

layout_gravity属性相同时报错

解决: 一左一右

IllegalStateException: Child drawer has absolute gravity LEFT

but this DrawerLayout already has a drawer view along that edge

非法状态异常:子抽屉有了绝对向左的重力,但这个抽屉布局在边缘已有抽屉控件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 抽屉布局是一种常用的 UI 设计模,允许用户通过向左或向右滑动屏幕来打开或关闭一个侧边栏菜单。以下是一个简单的实现步骤: 1. 在 XML 布局文件中添加 DrawerLayout 和两个子视图:主视图和抽屉视图。 ``` <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent"/> <ListView android:id="@+id/drawer_list" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="#ffffff"/> </android.support.v4.widget.DrawerLayout> ``` 2. 在 Java 代码中找到 DrawerLayout 和两个子视图的引用。 ``` DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); FrameLayout mainContent = (FrameLayout) findViewById(R.id.main_content); ListView drawerList = (ListView) findViewById(R.id.drawer_list); ``` 3. 创建一个 ArrayAdapter 以提供抽屉视图的数据。 ``` String[] menuItems = {"Item 1", "Item 2", "Item 3"}; ArrayAdapter<String> drawerListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, menuItems); drawerList.setAdapter(drawerListAdapter); ``` 4. 设置 ActionBarDrawerToggle 作为 DrawerLayout 的开关。 ``` ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close); drawerLayout.addDrawerListener(drawerToggle); drawerToggle.syncState(); ``` 5. 在 onOptionsItemSelected() 方法中调用 ActionBarDrawerToggle 的 onOptionsItemSelected() 方法。 ``` @Override public boolean onOptionsItemSelected(MenuItem item) { if (drawerToggle.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } ``` 完成以上步骤后,就可以在应用程序中添加抽屉布局了。用户可以通过向左或向右滑动屏幕来打开或关闭侧边栏菜单。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值