热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android简单实现悬浮吸附的FloatingView

***@ProjectName:yqf-android*@Package:com.jao.pointsystem.weight*@ClassName:ScrollFloatinig

/**
* @ProjectName: yqf-android
* @Package: com.jao.pointsystem.weight
* @ClassName: ScrollFloatinigButton
* @Description: java类作用描述
* @Author: OlderJiao
* @CreateDate: 2020/3/24 10:47
* @UpdateUser: 更新者:
* @UpdateDate: 2020/3/24 10:47
* @Version: 1.0
*/

@SuppressLint("AppCompatCustomView")
public class ScrollFloatinigButton extends FrameLayout {
private static final String TAG = "ScrollFloatinigButton";
private float mX;
private float mY;
private int mParentWidth;
private int mParentHeight;
private boolean mScrollEnable = true;
private int mScrollLeft;
private int mScrollTop;
private int mRight;
private int mScrollRight;
private int mScrollBottom;
private boolean hasScroll;
boolean isScroll = false;
private boolean isAdsorb = true;//是否自动吸附到两边
public ScrollFloatinigButton(Context context) {
this(context, null);
}
public ScrollFloatinigButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollFloatinigButton(Context context, AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrollFloatinigView);
mScrollEnable = ta.getBoolean(R.styleable.ScrollFloatinigView_scrollEnable, true);
ta.recycle();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//防止布局重置时重置ScrollFloatinigView的位置
ViewParent parent = getParent();
if (parent instanceof ViewGroup) {
((ViewGroup) getParent()).addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (hasScroll && mScrollRight != 0 && mScrollBottom != 0)
layout(mScrollLeft, mScrollTop, mScrollRight, mScrollBottom);
}
});
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (getParent() instanceof ViewGroup) {
mParentWidth = ((ViewGroup) getParent()).getWidth();
mParentHeight = ((ViewGroup) getParent()).getHeight();
}
Log.i(TAG, "onSizeChanged: ");
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!mScrollEnable) return super.onTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mX = ev.getX();
mY = ev.getY();
super.onTouchEvent(ev);
return true;
case MotionEvent.ACTION_MOVE:
int scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
float x = ev.getX();
float y = ev.getY();
x = x - mX;
y = y - mY;
if (Math.abs(scaledTouchSlop) < Math.abs(x) || Math.abs(scaledTouchSlop) < Math.abs(y)) {
isScroll &#061; true;
}
if (isScroll) {
mScrollLeft &#061; (int) (getX() &#043; x);
mScrollTop &#061; (int) (getY() &#043; y);
mScrollRight &#061; (int) (getX() &#043; getWidth() &#043; x);
mScrollBottom &#061; (int) (getY() &#043; getHeight() &#043; y);
//防止滑出父界面
if (mScrollLeft < 0 || mScrollRight > mParentWidth) {
mScrollLeft &#061; (int) getX();
mScrollRight &#061; (int) getX() &#043; getWidth();
}
if (mScrollTop < 0 || mScrollBottom > mParentHeight) {
mScrollTop &#061; (int) getY();
mScrollBottom &#061; (int) getY() &#043; getHeight();
}
layout(mScrollLeft, mScrollTop, mScrollRight, mScrollBottom);
hasScroll &#061; true;
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (isScroll) {
isScroll &#061; false;
setPressed(false);//重置点击状态
if (isAdsorb) {//判断是否开启吸附
//获取屏幕中间值
int mind &#061; getScreenWidth() / 2;
//获取控件宽度的中间值
int viewWithMind &#061; getWidth() / 2;
//手指抬起时 自动吸附到屏幕两边
if (mScrollLeft &#043; viewWithMind > mind) {
mScrollRight &#061; getScreenWidth();
mScrollLeft &#061; getScreenWidth() - getWidth();
} else {
mScrollRight &#061; getWidth();
mScrollLeft &#061; 0;
}
layout(mScrollLeft, mScrollTop, mScrollRight, mScrollBottom);
}
return true;
}
break;
}
return super.onTouchEvent(ev);
}
public boolean isAdsorb() {
return isAdsorb;
}
public void setAdsorb(boolean adsorb) {
isAdsorb &#061; adsorb;
}
/**
* 得到屏幕宽度
*
* &#064;return
*/

private int getScreenWidth() {
WindowManager windowManager &#061; (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics &#061; new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels;
}
}

布局代码&#xff0c;引用一下控件就OK了


<androidx.constraintlayout.widget.ConstraintLayout xmlns:android&#061;"http://schemas.android.com/apk/res/android"
xmlns:app&#061;"http://schemas.android.com/apk/res-auto"
xmlns:tools&#061;"http://schemas.android.com/tools"
android:layout_width&#061;"match_parent"
android:layout_height&#061;"match_parent"
tools:context&#061;".ZoomActivity">

<com.example.test.widget.ScrollFloatinigButton
android:layout_width&#061;"100dp"
android:layout_height&#061;"150dp"
android:layout_marginRight&#061;"20dp"
android:layout_marginBottom&#061;"50dp"
android:background&#061;"&#064;color/gray"
app:layout_constraintBottom_toBottomOf&#061;"parent"
app:layout_constraintRight_toRightOf&#061;"parent" />

androidx.constraintlayout.widget.ConstraintLayout>

自定义的属性


<declare-styleable name&#061;"ScrollFloatinigView">
<attr name&#061;"scrollEnable" format&#061;"boolean" />
declare-styleable>

有问题欢迎指正&#xff0c;共同学习&#xff0c;共同进步


本文地址:https://blog.csdn.net/qq_44946212/article/details/110648463



推荐阅读
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
author-avatar
然然妈1
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有