先看看QQ的侧滑效果
分析一下
先上原理图(不知道能否表达的清楚 ==)
-首先这里使用了 Android 的HorizontalScrollView 水平滑动布局作为容器,当然我们需要继承它自定义一个侧滑视图
- 这个容器里面有一个父布局(一般用LinerLayout,本demo用的是),这个父布局里面有且只有两个子控件(布局),初始状态菜单页的位置在Y轴上存在偏移这样可以就可以形成主页叠在菜单页的上方的视觉效果;然后在滑动的过程程中 逐渐修正偏移,最后菜单页和主页并排排列。原理搞清了实现起来就不是事儿了……
具体实现
布局代码
<fierce_luk.com.sideslipviewdemo2.SideslipView
android:id="@+id/my_veiw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
luk:leftPanding="200dp">
<!--如果菜单在左边直接用 LinearLayout-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/image2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/homepage"
android:gravity="center"
android:tag="0"
android:text="菜单"
android:textColor="@color/colorAccent"
android:textSize="60sp" />
<TextView
android:id="@+id/image1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color1"
android:gravity="center"
android:tag="1"
android:text="主页面"
android:textColor="@color/colorAccent"
android:textSize="60sp" />
</FrameLayout>
<!--<fragment-->
<!--android:name="com.luk.bluetoothapp.fragment.MyBluetoothDevice"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:tag="1" />-->
<!--<fragment-->
<!--android:name="com.luk.bluetoothapp.fragment.HomeFragment"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:tag="0" />-->
</fierce_luk.com.sideslipviewdemo2.SideslipView>
自定义的侧滑视图
最核心的部分
public class SideslipView extends HorizontalScrollView {
private int mScreenWidth;//屏幕宽度
private int mMenuLeftPadding;
private int mBluetoothWidth;//菜单的宽度
private int mHalfMenuWidth;
View home;
View bluetooth;
protected boolean isOpen;
protected boolean isFirst = true;
public SideslipView(Context context) {
// super 改 this
this(context, null);
}
public SideslipView(Context context, AttributeSet attrs) {
// super 改 this
this(context, attrs, 0);
}
public SideslipView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//测量屏幕宽度
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
// mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
Log.e("TAG", "MyScrollView: mScreenWidth" + mScreenWidth);
//获取 自定义的属性值
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyScrollView);
int n = a.length();
for (int i = 0; i < n; i++) {
int arrt = a.getIndex(i);
switch (arrt) {
case R.styleable.MyScrollView_leftPanding:
mMenuLeftPadding = (int) a.getDimension(R.styleable.MyScrollView_leftPanding, 0);
break;
default:
break;
}
}
Log.e("TAG", "MyScrollView: mMenuLeftPadding" + mMenuLeftPadding);
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isFirst) {
//获取子布局 并设置宽度
//如果菜单在左边 用LinearLayout就行
// LinearLayout layout = (LinearLayout) this.getChildAt(0);
/**此处因为 把侧边拉出页面设置在了右边 所有用 FrameLayout
* 不然在设置偏移量时 隐藏的侧边菜单会跑到主页面的上面*/
FrameLayout layout = (FrameLayout) this.getChildAt(0);
home = layout.getChildAt(1);
bluetooth = layout.getChildAt(0);
LayoutParams params = new LayoutParams(mBluetoothWidth,
getResources().getDisplayMetrics().heightPixels);
params.setMargins(mScreenWidth, 0, 0, 0);
bluetooth.setLayoutParams(params);
mBluetoothWidth = mScreenWidth - mMenuLeftPadding;
home.getLayoutParams().width = mScreenWidth;
bluetooth.getLayoutParams().width = mBluetoothWidth;
mHalfMenuWidth = mBluetoothWidth / 2;
isFirst = false;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//首先隐藏 Bluetooth
if (changed)
this.scrollTo(0, mBluetoothWidth);
}
Animation anim;
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
if (scrollX >= mHalfMenuWidth) {
Log.e("TAG", "====");
this.smoothScrollTo(mBluetoothWidth, 0);
isOpen = true;
} else {
this.smoothScrollTo(0, 0);
isOpen = false;
}
//必须消耗事件
return true;
}
return super.onTouchEvent(ev);
//return true;
}
/**
* 打开菜单栏
*/
protected void openMenu() {
if (isOpen)
return;
this.smoothScrollTo(mBluetoothWidth, 0);
isOpen = true;
}
/**
* 关闭菜单栏
*/
protected void closeMenu() {
if (!isOpen)
return;
this.smoothScrollTo(0, 0);
isOpen = false;
}
/**
* 按钮切换菜单
*/
public void toggleMenu() {
if (isOpen)
closeMenu();
else
openMenu();
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
//此处 l 起始值为零(没有偏移)
Log.e("TAG", "l=" + l + " t=" + t);
Log.e("TAG", "oldl=" + oldl + " oldt=" + oldt);
// scale 在 1 到 0 之间
float scale = l * 1.0f / mBluetoothWidth;
/**
* 抽屉式侧滑
* scaleLeft 从默认偏移量到偏移量 为零
*实现
* */
float scaleLeft = 0.4f - 0.4f * scale;
/**设置 X 轴方向的偏移量**/
ViewHelper.setTranslationX(bluetooth, -(mBluetoothWidth * scaleLeft));
Log.e("TAG", "mBluetoothWidth+" + mBluetoothWidth);
Log.e("TAG", "=============" + mBluetoothWidth * scale + "scale" + scale);
/*
*//**设置缩放时的 轴心点**//*
//此处轴心为右边界的中点
ViewHelper.setPivotY(home, mScreenWidth);
ViewHelper.setPivotX(home, home.getHeight() / 2);
*//**设置 XY轴方向的 缩放动画(从 1 到 0.9)**//*
float pivoXY = 1 - 0.4f * scale;
ViewHelper.setScaleX(home, pivoXY);
ViewHelper.setScaleY(home, pivoXY);*/
/*
*//**设置透明度**//*
//从 1 到 0.6;
float alpha = 1 - 0.4f * scale;
ViewHelper.setAlpha(home, alpha);*/
}
}
扩展
添加之定义属性 让用户配置菜单距离右边的边距的值;
首先在values文件夹下新建一个attr.xml,写入以下内容:
<resources>
<declare-styleable name="MyScrollView">
<attr name="rightPanding" format="dimension" />
<attr name="leftPanding" format="dimension" />
</declare-styleable>
</resources>
在布局里设置边距
<fierce_luk.com.sideslipviewdemo2.SideslipView
android:id="@+id/my_veiw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
luk:leftPanding="200dp">
其他的就不赘述了,看看效果
- 源码下载Demo源码点击下载
总结
以上所述是小编给大家介绍的Android自定义View 仿QQ侧滑菜单的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# android
# 自定义view
# qq
# 侧滑菜单
# Android解决viewpager嵌套滑动冲突并保留侧滑菜单功能
# Android自定义HorizontalScrollView实现qq侧滑菜单
# android RecyclerView侧滑菜单
# 滑动删除
# 长按拖拽
# 下拉刷新上拉加载
# Android自定义ViewGroup(侧滑菜单)详解及简单实例
# Android控件View打造完美的自定义侧滑菜单
# Android使用自定义控件HorizontalScrollView打造史上最简单的侧滑菜单
# 自定义
# 偏移量
# 小编
# 拉出
# 的是
# 在此
# 就不
# 其他的
# 就行
# 跑到
# 给大家
# 点击下载
# 所述
# 给我留言
# 值为
# 感谢大家
# 为零
# 就可以
# 源码下载
# 清了
相关文章:
深圳网站制作培训,深圳哪些招聘网站比较好?
建站之星免费版是否永久可用?
制作销售网站教学视频,销售网站有哪些?
简历在线制作网站免费版,如何创建个人简历?
子杰智能建站系统|零代码开发与AI生成SEO优化指南
南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?
,怎么用自己头像做动态表情包?
宝塔建站无法访问?如何排查配置与端口问题?
建站之星×万网:智能建站系统+自助建站平台一键生成
宝塔Windows建站如何避免显示默认IIS页面?
网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?
网站制作与设计教程,如何制作一个企业网站,建设网站的基本步骤有哪些?
深圳企业网站制作设计,在深圳如何网上全流程注册公司?
如何在Golang中指定模块版本_使用go.mod控制版本号
网站制作软件有哪些,制图软件有哪些?
宝塔新建站点报错如何解决?
建站之星如何助力网站排名飙升?揭秘高效技巧
c++怎么使用类型萃取type_traits_c++ 模板元编程类型判断【方法】
如何基于PHP生成高效IDC网络公司建站源码?
如何破解联通资金短缺导致的基站建设难题?
图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
高端企业智能建站程序:SEO优化与响应式模板定制开发
c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】
北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?
单页制作网站有哪些,朋友给我发了一个单页网站,我应该怎么修改才能把他变成自己的呢,请求高手指点迷津?
公司门户网站制作流程,华为官网怎么做?
为什么Go需要go mod文件_Go go mod文件作用说明
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
如何构建满足综合性能需求的优质建站方案?
大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?
专业公司网站制作公司,用什么语言做企业网站比较好?
,怎么在广州志愿者网站注册?
南宁网站建设制作定制,南宁网站建设可以定制吗?
如何用5美元大硬盘VPS安全高效搭建个人网站?
临沂网站制作公司有哪些,临沂第四中学官网?
网站图片在线制作软件,怎么在图片上做链接?
宝盒自助建站智能生成技巧:SEO优化与关键词设置指南
建站之星Pro快速搭建教程:模板选择与功能配置指南
如何批量查询域名的建站时间记录?
制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?
XML的“混合内容”是什么 怎么用DTD或XSD定义
深入理解Android中的xmlns:tools属性
外贸公司网站制作,外贸网站建设一般有哪些步骤?
如何在Windows服务器上快速搭建网站?
香港网站服务器数量如何影响SEO优化效果?
如何选择美橙互联多站合一建站方案?
如何用AWS免费套餐快速搭建高效网站?
建站DNS解析失败?如何正确配置域名服务器?
网站制作软件免费下载安装,有哪些免费下载的软件网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。