欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android运用onTouchEvent自定义滑动布局

程序员文章站 2023-08-16 23:18:10
写在自定义之前 我们也许会遇到,自定义控件的触屏事件处理,先来了解一下view类中的,ontouch事件和ontouchevent事件。 1、boolean ont...

写在自定义之前

我们也许会遇到,自定义控件的触屏事件处理,先来了解一下view类中的,ontouch事件和ontouchevent事件。

1、boolean ontouch(view v, motionvent event)
触摸事件发送到视图时调用(v:视图,event:触摸事件)
返回true:事件被完全消耗(即,从down事件开始,触发move,up所有的事件)
返回fasle:事件未被完全消耗(即,只会消耗掉down事件)

2、boolean ontouchevent(motionevent event)
触摸屏幕时调用
返回值,同上

须知

1、ontouch优先级比ontouchevent高
2、如果button设置了ontouchlistener监听,ontouch方法返回了true,就不会调用这个button的click事件

运用ontouchevent写一个能滑动的布局

需求:

1.刚进入界面外层布局,自动下滑一段距离,露出内层布局。
2.外层布局可以上下滑动,并且带有透明度渐变效果,改变内边距效果。

需求分析:

1.显然,外层布局要默认覆盖内层布局了,这个容易。自动下滑,要用到动画,objectanimator
2.外层布局要实现上下滑动,那么需要自定义,对ontouchevent重写(核心逻辑)
也许描述的有一些模糊,看一下效果图:

效果图:

Android运用onTouchEvent自定义滑动布局

下面是源码,demo链接地址

/** 
 * author:biligle. 
 * 自定义布局 
 */ 
 
public class myviewgroup extends viewgroup { 
 
 private myviewgrouplistener listener;//接口,监听滑动事件 
 private int vertical = 0;//布局距离顶端距离(默认0) 
 
 public myviewgroup(context context) { 
  super(context); 
 } 
 
 public myviewgroup(context context, attributeset attrs) { 
  super(context, attrs); 
 } 
 
 public myviewgroup(context context, attributeset attrs, int defstyleattr) { 
  super(context, attrs, defstyleattr); 
 } 
 
 @requiresapi(api = build.version_codes.lollipop) 
 public myviewgroup(context context, attributeset attrs, int defstyleattr, int defstyleres) { 
  super(context, attrs, defstyleattr, defstyleres); 
 } 
 
 
 private int downy = 0;//按下时的点 
 private int slide = 0;//最终移动距离 
 @override 
 public boolean ontouchevent(motionevent event) { 
  switch (event.getaction()){ 
   case motionevent.action_down: 
    downy = (int) event.gety(); 
    break; 
   case motionevent.action_move: 
    slide = downy - (int)event.gety(); 
    if(slide < 0){//下滑 
     vertical = listener.margintop(math.abs(slide)); 
    }else if(slide > 0){//上滑 
     vertical = listener.margintop(-slide); 
    } 
    break; 
   case motionevent.action_up: 
    if(vertical < 300){ 
     //布局距离屏幕顶部小于300,就让布局充满整个屏幕 
     vertical = listener.margintop(0); 
    } 
    break; 
  } 
  return true; 
 } 
 
 /** 
  * 测量子view 
  * @param widthmeasurespec 
  * @param heightmeasurespec 
  */ 
 @override 
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
  super.onmeasure(widthmeasurespec, heightmeasurespec); 
  for (int i = 0; i < getchildcount(); i++) { 
   view child = getchildat(i); 
   //系统测量 
   measurechild(child, widthmeasurespec, heightmeasurespec); 
  } 
 } 
 
 /** 
  * 安排子view的位置 
  * @param changed 
  * @param l 左边距 
  * @param t 上边距 
  * @param r 右边距 
  * @param b 下边距 
  */ 
 @override 
 protected void onlayout(boolean changed, int l, int t, int r, int b) { 
  int left = 0, top = 0, right = 0, bottom = 0; 
  for (int i = 0; i < getchildcount(); i++) { 
   view child = getchildat(i); 
   right = left + child.getmeasuredwidth(); 
   bottom = top + child.getmeasuredheight(); 
   child.layout(left, top, right, bottom); 
  } 
 } 
 
 public void setlistener(myviewgrouplistener listener){ 
  this.listener = listener; 
 } 
 
 interface myviewgrouplistener { 
  /** 
   * 设置topmargin,上下滑动时触发 
   * @param slide 滑动距离 
   * @return 当前上边距 
   */ 
  int margintop(int slide); 
 } 
}

public class mainactivity extends appcompatactivity implements myviewgroup.myviewgrouplistener{ 
 
 /** 自定义布局(外层布局)*/ 
 private myviewgroup myviewgroup; 
 /** 两个圆形图(在外层布局)*/ 
 private imageview iv1,iv2/*,cloud*/; 
 /** 包裹圆形图的布局*/ 
 private relativelayout relativelayout; 
 /** 外层布局参数类(这里用到了params.topmargin:上边距)*/ 
 private viewgroup.marginlayoutparams params; 
 /** 透明值(改变两个圆图的透明值)*/ 
 private float f; 
 /** 左右内边距(改变relativelayout内边距)*/ 
 private int p; 
 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  setcontentview(r.layout.activity_main); 
  myviewgroup = (myviewgroup) findviewbyid(r.id.my); 
  myviewgroup.setlistener(this); 
  iv1 = (imageview) findviewbyid(r.id.iv1); 
  iv2 = (imageview) findviewbyid(r.id.iv2); 
  relativelayout = (relativelayout) findviewbyid(r.id.relative); 
  params = (viewgroup.marginlayoutparams) myviewgroup.getlayoutparams(); 
  //初始化动画(自动下滑一段儿距离),我这里写死了900 
  objectanimator animator = objectanimator.offloat(myviewgroup,"translationy", 900); 
  animator.setduration(2000); 
  animator.addupdatelistener(new valueanimator.animatorupdatelistener() { 
   @override 
   public void onanimationupdate(valueanimator animation) { 
    float y = (float)animation.getanimatedvalue(); 
    f = y/800; 
    p = (int) y/3; 
    alpha(f); 
    padding(p); 
   } 
  }); 
  animator.start(); 
//  cloud = (imageview) findviewbyid(r.id.cloud); 
 } 
 
 
 /** 
  * 设置上边距 
  * @param slide 滑动距离 
  * @return 返回下滑布局,距离屏幕左上角的垂直距离 
  */ 
 @override 
 public int margintop(int slide) { 
  params.topmargin += slide; 
  myviewgroup.setlayoutparams(params); 
  int vertical = (900 + params.topmargin); 
  if(slide == 0){ 
   //为了隐藏两张圆图,所以把relativelayout的高度一并减除。 
   params.topmargin -= (vertical+relativelayout.getheight()); 
   myviewgroup.setlayoutparams(params); 
  } 
  float alpha = f + (float) params.topmargin/800;//自定义一个算法 
  alpha(alpha); 
  int padding = p + params.topmargin/3;//自定义一个算法 
  padding(padding); 
  return vertical; 
 } 
 
 /** 
  * 设置透明度 
  * @param alpha 透明值 
  */ 
 public void alpha(float alpha) { 
  iv1.setalpha(alpha); 
  iv2.setalpha(alpha); 
 } 
 
 /** 
  * 设置左右边距 
  * @param padding 边距值 
  */ 
 public void padding(int padding) { 
  relativelayout.setpadding(padding, 0, padding, 0); 
 } 
<?xml version="1.0" encoding="utf-8"?> 
<relativelayout 
 xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:app="http://schemas.android.com/apk/res-auto" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:id="@+id/activity_main" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 tools:context="com.wgl.viewgroup1.mainactivity"> 
 <imageview 
  android:id="@+id/iv" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:src="@mipmap/pic" 
  android:scaletype="fitxy"/> 
  <!--<imageview--> 
   <!--android:id="@+id/cloud"--> 
   <!--android:layout_width="wrap_content"--> 
   <!--android:layout_height="wrap_content"--> 
   <!--android:layout_centerhorizontal="true"--> 
   <!--android:alpha="0.8"--> 
   <!--android:src="@mipmap/cloud3"--> 
   <!--android:clickable="true"/>--> 
 
 <com.wgl.viewgroup1.myviewgroup 
  android:id="@+id/my" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:alpha="0.8" 
  android:layout_alignparenttop="true"> 
  <linearlayout 
   android:layout_width="match_parent" 
   android:layout_height="match_parent" 
   android:orientation="vertical"> 
   <relativelayout 
    android:id="@+id/relative" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal"> 
    <com.wgl.viewgroup1.circleimageview 
     android:id="@+id/iv1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:src="@mipmap/iv1" 
     app:civ_border_width="2dp" 
     app:civ_border_color="@color/coloraccent" 
     android:layout_alignparentleft="true"/> 
 
    <com.wgl.viewgroup1.circleimageview 
     android:id="@+id/iv2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:src="@mipmap/iv2" 
     app:civ_border_width="2dp" 
     app:civ_border_color="@color/coloraccent" 
     android:layout_alignparentright="true"/> 
   </relativelayout> 
   <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:alpha="0.8" 
    android:background="@color/colorprimary"> 
 
   </linearlayout> 
  </linearlayout> 
 
 </com.wgl.viewgroup1.myviewgroup> 
</relativelayout> 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。