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

利用HorizontalScrollView实现滑动页面时的缩放效果

程序员文章站 2022-05-27 10:07:15
在前面的文章中也有关于 horizontalscrollview 的使用:android使用horizontalscrollview实现水平滚动 。 这里主要实现的是向右...

在前面的文章中也有关于 horizontalscrollview 的使用:android使用horizontalscrollview实现水平滚动

这里主要实现的是向右滑动时,左侧的视图有逐渐放大,也会越来越清晰;向左滑动时,左侧的视图逐渐减小,逐渐变的模糊,且不移出屏幕左边缘的效果。效果如下(可以在主页面上的右侧向右滑动都可以实现该效果):

利用HorizontalScrollView实现滑动页面时的缩放效果

这里需要用到自定义的 horizontalscrollview ,让其作为布局文件的根标签。horizontalscrollview 里面只能有一个子组件,所以要把左侧的视图布局文件包含在 horizontalscrollview 的子组件里面。

activity_main.xml :

<com.crazy.reduce.reducesideslip xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/reduce_lay"
 android:layout_width="wrap_content"
 android:layout_height="match_parent"
 android:background="@drawable/bg"
 android:scrollbars="none"
 tools:context="com.crazy.reduce.mainactivity" >
 
 <linearlayout
  android:layout_width="wrap_content"
  android:layout_height="match_parent"
  android:orientation="horizontal" >
 
  <include layout="@layout/item" />
 
  <linearlayout
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="@drawable/bg_01" >
 
   <button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onclick="togglemenu"
    android:text="点击" />
  </linearlayout>
 </linearlayout>
 
</com.crazy.reduce.reducesideslip>

在 item.xml 布局文件的右边有个 button 按钮,这些都在 horizontalscrollview 的子组件当中。而 item.xml 究竟是怎样的布局也都不会影响到整个的滑动。

item.xml :

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
 
 <linearlayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_centerhorizontal="true"
  android:orientation="vertical" >
 
  <button
   android:id="@+id/bt_b"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_margintop="50dp"
   android:text="一个不同的按钮" />
 
  <imageview
   android:id="@+id/img"
   android:layout_width="wrap_content"
   android:layout_height="match_parent"
   android:scaletype="centercrop"
   android:src="@drawable/bg_03" />
 </linearlayout>
 
 
</relativelayout>

mainactivity.java :

package com.crazy.reduce;
 
import android.app.activity;
import android.os.bundle;
import android.view.view;
 
public class mainactivity extends activity {
 
 private reducesideslip rs;
 
 @override
 protected void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);
 
 rs = (reducesideslip)findviewbyid(r.id.reduce_lay);
 }
 
 public void togglemenu(view v) {
 rs.reduce();
 }
}

自定义的 reducesideslip.java :   需要 nineoldandroids-2.4.0.jar 包,其下载地址

package com.crazy.reduce;
 
import android.content.context;
import android.util.attributeset;
import android.view.motionevent;
import android.view.viewgroup;
import android.widget.framelayout;
import android.widget.horizontalscrollview;
import android.widget.linearlayout;
 
import com.nineoldandroids.view.viewhelper;
 
public class reducesideslip extends horizontalscrollview {
 
 private int mscreenwidth;  // 屏幕宽度
 private int mmnurightpadding = 300;
 
 private int mmenuwidth; // 视图宽度(左边的视图)
 private int mhalfmenuwidth;
 
 private boolean isopen; // 标记菜单是否打开
 private boolean once;  // 是否已经初始化回收菜单
 
 private viewgroup mmenu; // 左边的视图
 private viewgroup mcontent; // 右边的视图
 
 public reducesideslip(context context, attributeset attrs) {
  super(context, attrs);
  mscreenwidth = context.getresources().getdisplaymetrics().widthpixels;
 }
 
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 
  if (!once) {
   // 要与布局文件当中的一致
   linearlayout temp = (linearlayout)getchildat(0);
   mmenu = (viewgroup)temp.getchildat(0);
   mcontent = (viewgroup)temp.getchildat(1);
 
   mmenuwidth = mscreenwidth - mmnurightpadding;
   mhalfmenuwidth = mmenuwidth/2;
   mmenu.getlayoutparams().width = mmenuwidth;
   mcontent.getlayoutparams().width = mscreenwidth;
  }
  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);
 
  if (changed) {
   // 隐藏菜单
   this.scrollto(mmenuwidth, 0);
   once = true;
  }
 }
 
 public void reduce(){
  if (isopen) {
   closemenu();
  } else {
   openmenu();
  }
 }
 
 private void openmenu() {
  if (isopen) {
   return;
  }
  // 和 scrollto() 相似,但是要缓和些,
  // 不像 scrollto() 直接移动过去
  this.smoothscrollto(0, 0);
  isopen = true;
 }
 
 private void closemenu() {
  if (isopen) {
   this.smoothscrollto(mmenuwidth, 0);
   isopen = false;
  }
 }
 
 @override
 public boolean ontouchevent(motionevent ev) {
  switch (ev.getaction()){
   case motionevent.action_up:  // 松开手
    int scrollx = getscrollx();   // 水平滑动的距离
    if (scrollx > mhalfmenuwidth) {
     this.smoothscrollto(mmenuwidth, 0);
     isopen = false;
    } else {
     this.smoothscrollto(0, 0);
     isopen = true;
    }
    return true;
  }
  return super.ontouchevent(ev);
 }
 
 @override
 protected void onscrollchanged(int l, int t, int oldl, int oldt) {
  super.onscrollchanged(l, t, oldl, oldt);
 
  // 左右视图切换时的渐变范围 (注意是 l 不是1(一))
  float scale = l*1.0f/mmenuwidth;  // 范围值 (0, 1)
  float leftscale = 1- 0.3f*scale;  // 范围值(0.7, 1)
  float rightscale = 0.8f + 0.2f*scale; // 范围值 (0.8, 1)
 
  viewhelper.setscalex(mmenu, leftscale);
  viewhelper.setscaley(mmenu, leftscale);
 
  // 往右滑动时,左边的视图逐渐变亮
  viewhelper.setalpha(mmenu, 0.6f + 0.4f * (1 - scale)); // (0.6, 1)
  // 往左滑动时,左边的视图不用移除屏幕左边界(可以不要) 
  viewhelper.settranslationx(mmenu, mmenuwidth * scale * 0.7f);
 
  viewhelper.setscalex(mcontent, rightscale);
  viewhelper.setscaley(mcontent, rightscale);
 }
}

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