Android View滚动、拉伸到顶/底部弹性回弹复位



《Android View滚动、拉伸到顶/底部弹性回弹复位》

我在上一篇文章介绍了如何实现一个Android ListView拉到顶/底部后,像橡皮筋一样弹性回弹复位(《Android ListView拉到顶/底部,像橡皮筋一样弹性回弹复位》,文章链接地址: http://blog.csdn.net/zhangphil/article/details/47311155 )。事实上,Android凡是由ScrollView包裹的控件,均可实现滚动到顶/底部,弹性回弹复位的交互设计效果。关键点是重写Android原生ScrollView的overScrollBy()方法。
现给出实现代码和步骤:
(1)首先需要写一个View继承自ScrollView,然后重写关键的方法:overScrollBy()。假设该view就叫做ZhangPhilScrollView:

  1. package zhangphil.view;  
  2.   
  3. import android.annotation.SuppressLint;  
  4. import android.content.Context;  
  5. import android.util.AttributeSet;  
  6. import android.util.DisplayMetrics;  
  7. import android.widget.ScrollView;  
  8.   
  9. public class ZhangPhilScrollView extends ScrollView{  
  10.   
  11.     // 这个值控制可以把ScrollView包裹的控件拉出偏离顶部或底部的距离。  
  12.     private static final int MAX_OVERSCROLL_Y = 200;  
  13.   
  14.     private Context mContext;  
  15.     private int newMaxOverScrollY;  
  16.   
  17.     public ZhangPhilScrollView(Context context) {  
  18.         super(context);  
  19.           
  20.         init(context);  
  21.     }  
  22.   
  23.     public ZhangPhilScrollView(Context context, AttributeSet attrs) {  
  24.         super(context, attrs);  
  25.           
  26.         init(context);  
  27.     }  
  28.   
  29.     /* 
  30.      * public ZhangPhilListView(Context context, AttributeSet attrs, int 
  31.      * defStyle) { super(context, attrs, defStyle); this.mContext = context; 
  32.      * init(); } 
  33.      */  
  34.   
  35.     @SuppressLint("NewApi")  
  36.     private void init(Context context) {  
  37.           
  38.         this.mContext = context;  
  39.           
  40.         DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();  
  41.         float density = metrics.density;  
  42.         newMaxOverScrollY = (int) (density * MAX_OVERSCROLL_Y);  
  43.           
  44.         //false:隐藏ScrollView的滚动条。  
  45.         this.setVerticalScrollBarEnabled(false);  
  46.           
  47.         //不管装载的控件填充的数据是否满屏,都允许橡皮筋一样的弹性回弹。  
  48.         this.setOverScrollMode(ScrollView.OVER_SCROLL_ALWAYS);  
  49.     }  
  50.   
  51.     // 最关键的地方。  
  52.     //支持到SDK8需要增加@SuppressLint("NewApi")。  
  53.     @SuppressLint("NewApi")  
  54.     @Override  
  55.     protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,  
  56.             int scrollY, int scrollRangeX, int scrollRangeY,  
  57.             int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {  
  58.         return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,  
  59.                 scrollRangeX, scrollRangeY, maxOverScrollX, newMaxOverScrollY,  
  60.                 isTouchEvent);  
  61.     }  
  62. }  
package zhangphil.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.ScrollView;

public class ZhangPhilScrollView extends ScrollView{

	// 这个值控制可以把ScrollView包裹的控件拉出偏离顶部或底部的距离。
	private static final int MAX_OVERSCROLL_Y = 200;

	private Context mContext;
	private int newMaxOverScrollY;

	public ZhangPhilScrollView(Context context) {
		super(context);
		
		init(context);
	}

	public ZhangPhilScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		init(context);
	}

	/*
	 * public ZhangPhilListView(Context context, AttributeSet attrs, int
	 * defStyle) { super(context, attrs, defStyle); this.mContext = context;
	 * init(); }
	 */

	@SuppressLint("NewApi")
	private void init(Context context) {
		
		this.mContext = context;
		
		DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
		float density = metrics.density;
		newMaxOverScrollY = (int) (density * MAX_OVERSCROLL_Y);
		
		//false:隐藏ScrollView的滚动条。
		this.setVerticalScrollBarEnabled(false);
		
		//不管装载的控件填充的数据是否满屏,都允许橡皮筋一样的弹性回弹。
		this.setOverScrollMode(ScrollView.OVER_SCROLL_ALWAYS);
	}

	// 最关键的地方。
	//支持到SDK8需要增加@SuppressLint("NewApi")。
	@SuppressLint("NewApi")
	@Override
	protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
			int scrollY, int scrollRangeX, int scrollRangeY,
			int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
				scrollRangeX, scrollRangeY, maxOverScrollX, newMaxOverScrollY,
				isTouchEvent);
	}
}


(2)然后在布局文件代码中像使用Android原生的ScrollView一样使用ZhangPhilScrollView包裹需要实现弹性回弹交互设计的组件,在我的这个例子中,出于简单的目的,假设ZhangPhilScrollView包裹的只是一个TextView:

  1. <zhangphil.view.ZhangPhilScrollView xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="match_parent"  
  3.     android:layout_height="match_parent" >  
  4.   
  5.     <TextView  
  6.         android:id="@+id/text"  
  7.         android:layout_width="match_parent"  
  8.         android:layout_height="wrap_content" />  
  9.   
  10. </zhangphil.view.ZhangPhilScrollView>  
<zhangphil.view.ZhangPhilScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</zhangphil.view.ZhangPhilScrollView>


测试:

  1. package zhangphil.view;  
  2.   
  3. import zhangphil.view.R;  
  4. import android.support.v7.app.ActionBarActivity;  
  5. import android.widget.TextView;  
  6. import android.graphics.Color;  
  7. import android.os.Bundle;  
  8.   
  9. public class MainActivity extends ActionBarActivity {  
  10.   
  11.     @Override  
  12.     protected void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.activity_main);  
  15.   
  16.         TextView text = (TextView) findViewById(R.id.text);  
  17.   
  18.         // 测试数据集。  
  19.         String s = "";  
  20.         for (int i = 0; i < 10; i++) {  
  21.             s += i + "\n";  
  22.         }  
  23.   
  24.         text.setText(s);  
  25.   
  26.         // 设置TextView的背景颜色,更容易观察出弹性回弹效果。  
  27.         text.setBackgroundColor(Color.RED);  
  28.     }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# -*- coding: UTF-8 -*- from lib2to3.pgen2 import driver from appium import webdriver from appium.webdriver.common.appiumby import AppiumBy el1 = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="通讯录") el1.click() el2 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.widget.ListView/android.widget.FrameLayout[3]/android.widget.RelativeLayout") el2.click() el3 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[1]/android.widget.TextView") el3.click() el4 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[8]") el4.click() el5 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[11]") el5.click()
最新发布
06-08
根据你提供的代码,看起来你使用了 `lib2to3.pgen2.driver` 模块中的 `find_element` 方法。但是,`lib2to3.pgen2.driver` 模块实际上并没有这个方法,所以出现了 `AttributeError`。 我猜测你可能是想使用 Appium 的 `driver.find_element` 方法。如果是这样的话,你需要更改你的代码来正确导入 `appium.webdriver` 模块并使用它的 `driver` 属性。具体的修改如下: ```python # -*- coding: UTF-8 -*- from appium import webdriver from appium.webdriver.common.appiumby import AppiumBy # 创建 Appium driver desired_caps = {} desired_caps['platformName'] = 'Android' # 添加其他的 desired capabilities 选项... driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) # 执行测试操作 el1 = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="通讯录") el1.click() el2 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.widget.ListView/android.widget.FrameLayout[3]/android.widget.RelativeLayout") el2.click() el3 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[1]/android.widget.TextView") el3.click() el4 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[8]") el4.click() el5 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[11]") el5.click() # 关闭 driver driver.quit() ``` 注意,这里我使用了 `appium.webdriver` 模块的 `webdriver.Remote` 方法来创建 driver,然后使用 `driver.find_element` 方法来查找元素。最后,在测试结束后,我也关闭了 driver。你需要根据你的具体情况修改代码中的 `desired_caps` 和元素定位方式等内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值