Android自定义控件(四)——让每一个Activity UI都具有弹性
前面我们已经介绍了如何让你的ScrollView,ListView具有弹性,
今天,我们在前面的基础上,做一下适当的修改,让那些既不是ScrollView,也不是ListView的Activity页面,也能具有弹性。
先上图:
图中是最简单的一个Android测试程序。默认的效果TextView是无法划动的。
进过我们小小的改造,就能让整个UI具有弹性效果。
改动如下:
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- View view = getLayoutInflater().inflate(R.layout.activity_main, null);
- view.setOnTouchListener(new ElasticTouchListener());
- setContentView(view);
- }
我们仅仅只需要在需要弹性的Root VIew 上加上监听。就能达到如果的效果了。
ElasticTouchListener源码:
- public class ElasticTouchListener implements OnTouchListener {
- private View inner;
- View[] children;
- private float y;
- private Rect normal = new Rect();
- private boolean animationFinish = true;
- private int[] tops;
- private int[] bottoms;
- @Override
- public boolean onTouch(View v, MotionEvent ev) {
- if (inner == null && children == null) {
- if (v instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) v;
- int count = group.getChildCount();
- if (count > 0) {
- children = new View[count];
- tops = new int[count];
- bottoms = new int[count];
- for (int i = 0; i < count; i++) {
- children[i] = group.getChildAt(i);
- tops[i] = children[i].getTop();
- bottoms[i] = children[i].getBottom();
- }
- }
- }
- inner = v;
- }
- if (animationFinish && (inner != null || children != null)) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // System.out.println("ACTION_DOWN");
- y = ev.getY();
- break;
- case MotionEvent.ACTION_UP:
- // System.out.println("ACTION_UP");
- y = 0;
- if (isNeedAnimation()) {
- animation();
- }
- inner.invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- // System.out.println("ACTION_MOVE");
- final float preY = y == 0 ? ev.getY() : y;
- float nowY = ev.getY();
- int deltaY = (int) (preY - nowY);
- y = nowY;
- // 当滚动到最上或者最下时就不会再滚动,这时移动布局
- if (isNeedMove()) {
- if (normal.isEmpty()) {
- // 保存正常的布局位置
- normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());
- }
- if (children != null) {
- View view = null;
- for (int i = 0; i < children.length; i++) {
- view = children[i];
- view.layout(view.getLeft(), view.getTop() - deltaY / 2, view.getRight(), view.getBottom() - deltaY / 2);
- }
- } else {
- // 移动布局
- inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom() - deltaY / 2);
- }
- }
- inner.invalidate();
- break;
- default:
- break;
- }
- } else {
- return false;
- }
- return true;
- }
- // 开启动画移动
- public void animation() {
- if (children == null) {
- // 开启移动动画
- TranslateAnimation trans = new TranslateAnimation(0, 0, 0, normal.top - inner.getTop());
- trans.setDuration(200);
- trans.setAnimationListener(new AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- animationFinish = false;
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- inner.clearAnimation();
- // 设置回到正常的布局位置
- inner.layout(normal.left, normal.top, normal.right, normal.bottom);
- normal.setEmpty();
- animationFinish = true;
- }
- });
- inner.startAnimation(trans);
- } else {
- for (int i = 0; i < children.length; i++) {
- final View view = children[i];
- if (view.getVisibility() == View.VISIBLE) {
- final int index = i;
- // 开启移动动画
- TranslateAnimation trans = new TranslateAnimation(0, 0, 0, tops[i] - view.getTop());
- trans.setDuration(200);
- trans.setAnimationListener(new AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- animationFinish = false;
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- view.clearAnimation();
- // 设置回到正常的布局位置
- view.layout(view.getLeft(), tops[index], view.getRight(), bottoms[index]);
- normal.setEmpty();
- animationFinish = true;
- }
- });
- view.startAnimation(trans);
- }
- }
- }
- }
- // 是否需要开启动画
- public boolean isNeedAnimation() {
- return !normal.isEmpty();
- }
- // 是否需要移动布局
- public boolean isNeedMove() {
- // int offset = inner.getMeasuredHeight() - getHeight();
- // int scrollY = getScrollY();
- // if (scrollY == 0 || scrollY == offset) {
- // return true;
- // }
- // return false;
- // if (children != null && children.length > 0
- // && (children[children.length - 1].getBottom() <= inner.getPaddingTop()/*inner.getTop()*/
- // || children[0].getTop() >= inner.getHeight()
- // )) {
- // return false;
- // }
- return true;
- }
- }
本次教程就到此,
经过有弹性的ScrollView,有弹性的ListView,以及本文的介绍,就可以让你的Android应用在每一个角落都拥有弹性啦。
Android自定义控件(四)——让每一个Activity UI都具有弹性的更多相关文章
- android activity改变另一个activity ui
android开发之在activity中控制另一个activity的UI更新 转自:http://www.cnblogs.com/ycxyyzw/p/3875544.html 第一种方法: 遇到一 ...
- Android开发:向下一个activity传递数据,返回数据给上一个activity
1.向下一个activity传递数据 activity1 Button button=(Button) findViewById(R.id.button1); button.setOnClickLis ...
- android 案例:从另一个activity选择信息并获取返回值
主窗口: package com.example.test; import android.app.Activity; import android.app.AlertDialog; import a ...
- [android] 显示意图激活另外一个activity
可以使用跳转的方式类似javaweb来实现界面转换 显示意图就是必须要指定开启组件的具体信息,包名,组件名,组件的class 新建一个类TwoActivity ,继承Activity类,重写onCre ...
- Eclipse中在android项目中出现新建一个Activity后,出现整个project的报错以及包导入以后无法执行等等情况分析。
今天用Eclipse去写android项目,然后后面须要建一个Blank Activity后,非常正常的建立的.然后那个Activity是基于ActionBarAtivity,要导入v7,结果由于这 ...
- android 利用Handler触发另一个activity方法
如activityA代码: activityB = new ActivtyB(mHandler,CLOSE_SEARCH_MSG);//新建对像B传递,一个handler和Message,然后在act ...
- android自定义控件(四) View中的方法
onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) 确定所有子元素的大小 onLayout(boolean, int, int ...
- 【Android】12.3 在当前Activity中获取另一个Activity的返回值
分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 在上一节的示例中,通过StartActivity(Intent)方法启动另一个Activity后,这两个Activ ...
- Android基础整理之四大组件Activity
最近准备系统的重新整理复习一下Android的各方面的知识,本着知识分享的原则,我就把梳理过程中一些东西给记录下来,权当一个学习笔记吧. 下面步入正题..... 什么是Activity Activit ...
随机推荐
- jQuery之简单动画效果
1. show()显示动画 语法:show(speed,callback) Number/String,Function speend为动画执行时间,单位为毫秒.也可以为slow",&quo ...
- Log4Qt 使用(一)
一.下载 http://sourceforge.net/projects/log4qt/develop 二.Log4Qt介绍 Log4Qt 是Apache Log4J 的Qt移植版,所以看Log4J的 ...
- VLV INDEX
Normally, when the Directory Server conducts a search, the server looks through the entire entry for ...
- SUN-LDAP6.3_RHEL 5.0-卸载LDAP
卸载LDAP 1.注销服务器 到目录/ldap/ldapinstance/dscc6/bin下 # ./dsccreg remove-server -h 主机名 /ldap/ldapinstance/ ...
- 高仿QQ即时聊天软件开发系列之三登录窗口用户选择下拉框
上一篇高仿QQ即时聊天软件开发系列之二登录窗口界面写了一个大概的布局和原理 这一篇详细说下拉框的实现原理 先上最终效果图 一开始其实只是想给下拉框加一个placeholder效果,让下拉框在未选择未输 ...
- 武汉科技大学ACM :1010: 华科版C语言程序设计教程(第二版)例题7.8
Problem Description 输入一个用年月日表示的日期,求该日期是该年的第几天.输入某年的第几天,输出这一天是该年的几月几号,茂茂解不出,需要你的帮助. Input 开始有个整数k,表示询 ...
- Popular Cows (POJ No.2186)
Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= ...
- [Leetcode][015] 3Sum (Java)
题目在这里: https://leetcode.com/problems/3sum/ [标签] Array; Two Pointers [个人分析] 老实交待,这个题卡半天,第一次做不会,抄别人的.过 ...
- 《Linux多线程服务器端编程》读书笔记第3章
<Linux多线程服务器端编程>第3章主要讲的是多线程服务器的适用场合与常用的编程模型. 1.进程和线程 一个进程是"内存中正在运行的程序“.每个进程都有自己独立的地址空间(ad ...
- ExtJS4.2.1
ExtJS4.2.1 1. 介绍 1.1 说明 ExtJS是一个用javascript.CSS和HTML等技术实现的主要用于创建RIA即富客户端,且与后台技术无关的前端Ajax框架. 常用于企业内部管 ...