- 浏览: 2180901 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (1240)
- mac/IOS (287)
- flutter (1)
- J2EE (115)
- android基础知识 (582)
- android中级知识 (55)
- android组件(Widget)开发 (18)
- android 错误 (21)
- javascript (18)
- linux (70)
- 树莓派 (18)
- gwt/gxt (1)
- 工具(IDE)/包(jar) (18)
- web前端 (17)
- java 算法 (8)
- 其它 (5)
- chrome (7)
- 数据库 (8)
- 经济/金融 (0)
- english (2)
- HTML5 (7)
- 网络安全 (14)
- 设计欣赏/设计窗 (8)
- 汇编/C (8)
- 工具类 (4)
- 游戏 (5)
- 开发频道 (5)
- Android OpenGL (1)
- 科学 (4)
- 运维 (0)
- 好东西 (6)
- 美食 (1)
最新评论
-
liangzai_cool:
请教一下,文中,shell、C、Python三种方式控制led ...
树莓派 - MAX7219 -
jiazimo:
...
Kafka源码分析-序列5 -Producer -RecordAccumulator队列分析 -
hp321:
Windows该命令是不是需要安装什么软件才可以?我试过不行( ...
ImageIO读jpg的时候出现javax.imageio.IIOException: Unsupported Image Type -
hp321:
Chenzh_758 写道其实直接用一下代码就可以解决了:JP ...
ImageIO读jpg的时候出现javax.imageio.IIOException: Unsupported Image Type -
huanghonhpeng:
大哥你真强什么都会,研究研究。。。。小弟在这里学到了很多知识。 ...
android 浏览器
以前做一个看书的项目时,有个翻书的功能,当手指滑动书页移动一段然后抬起后,需要页面view自动完成剩余的操作:
1、当滑动距离大于某个设定值时,自动滚动到末尾处,翻一页。
2、当滑动距离小于该设定值时,自动回滚到起始处,还原。
实现这个功能,当时是用了Scroller来实现的。
我一步步来说下吧:
1、Scroller的最简单用法解释
网上有很多关于Scroller的用法,很多讲的真的很不错,但我觉得,他们的讲解还是过于繁琐,这里我就最最简单的说下吧,这个Scroller到底怎么回事,且看下面代码:
下面的这个demo1,就一个布局,linearlayout上放置一个button,点击button,我们就调用Scroller的相关方法:
布局文件xml:
控制器activity:
运行后,点击按钮,就可以看到效果,且看控制台日志输出:
从日志输出的数据一看,你应该能大致知道这个scroller的作用了吧
我们在button的事件处理里做的是调用了
这个方法,然后我们在线程中一直查看scroller的几个属性数值,然后打印了出来,从日志可以看出,scroller中的这些数值,是按(int startX, int startY, int dx, int dy)来变化的,并且是在intduration这个时间段内完成的。我们设置线程的睡眠时间是50毫秒,而打印了总共20条日志,20* 50 = 1000,正好是我们设置的这个时间。
如果我们在调用了
让我们的view重新绘制,并且利用scroller的几个属性数值来确定view的位置或其他的什么,然后不断的循环调用,你说会出现什么呢?答案就不用说了吧(view会动起来吧),这个就是我们平时在项目中利用scroller的主要思路了,而一般的时候,我们会多绕了几道弯儿而已。
2、Scroller结合view的用法
首先,我们简单的介绍下view,查看android的源码,你会发现如下的方法:
该方法就是留给我们去覆写的,它一般都会被该view的父类viewGroup在绘制该view时调用,具体的,就不多说了,大家可以参见相关博客,如果我们在这个方法里,调用 scroller的相关属性来修改view的相关属性或调用其他方法,是不是可以做很多事呢?
下面看看改造后的demo2:
先介绍一个函数,view下面的:
public void scrollTo (int x, int y) Added in API level 1
Set the scrolled position of your view. This will cause a call to onScrollChanged(int, int, int, int) and the view will be invalidated.
Parameters
x the x position to scroll to
y the y position to scroll to
该函数可以使view中的内容滚动到指定位置:
demo2:
该demo没有xml,直接就一个activity:
运行程序效果:
点击第一个button后,日志如下:
通过日志,看出什么了没?
另外,通过该日志,你了解了view的绘画机制没,应该能发现吧。
最终的效果图片:
点击buttom2,日志就不给出了,效果图片如下:
button内的文字移动到了不可见处,
所以调用scrollTo移动的将是该view的内容,如果是viewGroup的话,就移动了它的孩子view了
所以调用scrollTo移动的将是该实例的孩子,也就是MyButton实例
这会儿明白了没?
后面我会尝试的自己模拟一个scrolelr,其实他的作用就是存储一些基本的数值,其他的啥也没做,也和view没有真正关系的,它只是被动的被调用的
1、当滑动距离大于某个设定值时,自动滚动到末尾处,翻一页。
2、当滑动距离小于该设定值时,自动回滚到起始处,还原。
实现这个功能,当时是用了Scroller来实现的。
我一步步来说下吧:
1、Scroller的最简单用法解释
网上有很多关于Scroller的用法,很多讲的真的很不错,但我觉得,他们的讲解还是过于繁琐,这里我就最最简单的说下吧,这个Scroller到底怎么回事,且看下面代码:
下面的这个demo1,就一个布局,linearlayout上放置一个button,点击button,我们就调用Scroller的相关方法:
布局文件xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_margin="10dp" android:text="run Scroller " /> </LinearLayout>
控制器activity:
import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.LinearLayout; import android.widget.Scroller; public class MainActivity extends Activity { private Scroller mScroller; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mScroller = new Scroller(this); this.setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mScroller.startScroll(-10, -100,- 200, -300, 1000); new Thread(){ public void run() { while(mScroller.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。 { Log.i("scroller", "getCurrX()= "+mScroller.getCurrX()+" getCurrY()="+mScroller.getCurrY()); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } }); } }
运行后,点击按钮,就可以看到效果,且看控制台日志输出:
引用
05-02 11:30:55.455: I/scroller(30287): getCurrX()= -10 getCurrY()=-100
05-02 11:30:55.510: I/scroller(30287): getCurrX()= -26 getCurrY()=-124
05-02 11:30:55.557: I/scroller(30287): getCurrX()= -63 getCurrY()=-180
05-02 11:30:55.612: I/scroller(30287): getCurrX()= -111 getCurrY()=-251
05-02 11:30:55.658: I/scroller(30287): getCurrX()= -144 getCurrY()=-301
05-02 11:30:55.713: I/scroller(30287): getCurrX()= -166 getCurrY()=-334
05-02 11:30:55.760: I/scroller(30287): getCurrX()= -181 getCurrY()=-356
05-02 11:30:55.815: I/scroller(30287): getCurrX()= -191 getCurrY()=-371
05-02 11:30:55.862: I/scroller(30287): getCurrX()= -197 getCurrY()=-381
05-02 11:30:55.916: I/scroller(30287): getCurrX()= -201 getCurrY()=-387
05-02 11:30:55.963: I/scroller(30287): getCurrX()= -204 getCurrY()=-391
05-02 11:30:56.018: I/scroller(30287): getCurrX()= -206 getCurrY()=-394
05-02 11:30:56.065: I/scroller(30287): getCurrX()= -208 getCurrY()=-396
05-02 11:30:56.119: I/scroller(30287): getCurrX()= -208 getCurrY()=-398
05-02 11:30:56.166: I/scroller(30287): getCurrX()= -209 getCurrY()=-398
05-02 11:30:56.221: I/scroller(30287): getCurrX()= -209 getCurrY()=-399
05-02 11:30:56.268: I/scroller(30287): getCurrX()= -210 getCurrY()=-399
05-02 11:30:56.322: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:56.369: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:56.424: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:56.471: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:55.510: I/scroller(30287): getCurrX()= -26 getCurrY()=-124
05-02 11:30:55.557: I/scroller(30287): getCurrX()= -63 getCurrY()=-180
05-02 11:30:55.612: I/scroller(30287): getCurrX()= -111 getCurrY()=-251
05-02 11:30:55.658: I/scroller(30287): getCurrX()= -144 getCurrY()=-301
05-02 11:30:55.713: I/scroller(30287): getCurrX()= -166 getCurrY()=-334
05-02 11:30:55.760: I/scroller(30287): getCurrX()= -181 getCurrY()=-356
05-02 11:30:55.815: I/scroller(30287): getCurrX()= -191 getCurrY()=-371
05-02 11:30:55.862: I/scroller(30287): getCurrX()= -197 getCurrY()=-381
05-02 11:30:55.916: I/scroller(30287): getCurrX()= -201 getCurrY()=-387
05-02 11:30:55.963: I/scroller(30287): getCurrX()= -204 getCurrY()=-391
05-02 11:30:56.018: I/scroller(30287): getCurrX()= -206 getCurrY()=-394
05-02 11:30:56.065: I/scroller(30287): getCurrX()= -208 getCurrY()=-396
05-02 11:30:56.119: I/scroller(30287): getCurrX()= -208 getCurrY()=-398
05-02 11:30:56.166: I/scroller(30287): getCurrX()= -209 getCurrY()=-398
05-02 11:30:56.221: I/scroller(30287): getCurrX()= -209 getCurrY()=-399
05-02 11:30:56.268: I/scroller(30287): getCurrX()= -210 getCurrY()=-399
05-02 11:30:56.322: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:56.369: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:56.424: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
05-02 11:30:56.471: I/scroller(30287): getCurrX()= -210 getCurrY()=-400
从日志输出的数据一看,你应该能大致知道这个scroller的作用了吧
mScroller.startScroll(-10, -100,- 200, -300, 1000);
我们在button的事件处理里做的是调用了
public void startScroll (int startX, int startY, int dx, int dy,int duration)
这个方法,然后我们在线程中一直查看scroller的几个属性数值,然后打印了出来,从日志可以看出,scroller中的这些数值,是按(int startX, int startY, int dx, int dy)来变化的,并且是在intduration这个时间段内完成的。我们设置线程的睡眠时间是50毫秒,而打印了总共20条日志,20* 50 = 1000,正好是我们设置的这个时间。
如果我们在调用了
public void startScroll (int startX, int startY, int dx, int dy,in tduration)
让我们的view重新绘制,并且利用scroller的几个属性数值来确定view的位置或其他的什么,然后不断的循环调用,你说会出现什么呢?答案就不用说了吧(view会动起来吧),这个就是我们平时在项目中利用scroller的主要思路了,而一般的时候,我们会多绕了几道弯儿而已。
2、Scroller结合view的用法
首先,我们简单的介绍下view,查看android的源码,你会发现如下的方法:
/** * Called by a parent to request that a child update its values for mScrollX * and mScrollY if necessary. This will typically be done if the child is * animating a scroll using a {@link android.widget.Scroller Scroller} * object. */ public void computeScroll(){}
该方法就是留给我们去覆写的,它一般都会被该view的父类viewGroup在绘制该view时调用,具体的,就不多说了,大家可以参见相关博客,如果我们在这个方法里,调用 scroller的相关属性来修改view的相关属性或调用其他方法,是不是可以做很多事呢?
下面看看改造后的demo2:
先介绍一个函数,view下面的:
public void scrollTo (int x, int y) Added in API level 1
Set the scrolled position of your view. This will cause a call to onScrollChanged(int, int, int, int) and the view will be invalidated.
Parameters
x the x position to scroll to
y the y position to scroll to
该函数可以使view中的内容滚动到指定位置:
demo2:
该demo没有xml,直接就一个activity:
import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Scroller; public class MainActivity extends Activity { LinearLayout demoSubview1, demoSubview2, demoViewGroup; private Scroller mScrollerViewGroup; private Scroller mScrollerView; // private Scroller mScroller; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mScrollerViewGroup = new Scroller(this); mScrollerView = new Scroller(this); demoSubview1 = new DemoView(this); demoSubview2 = new DemoView(this); demoSubview1.setBackgroundColor(this.getResources().getColor( android.R.color.darker_gray)); demoSubview2.setBackgroundColor(this.getResources().getColor( android.R.color.white)); demoViewGroup = new DemoViewGroup(this); demoViewGroup.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams p0 = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); this.setContentView(demoViewGroup, p0); LinearLayout.LayoutParams p1 = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); p1.weight = 1; demoViewGroup.addView(demoSubview1, p1); LinearLayout.LayoutParams p2 = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); p2.weight = 1; demoViewGroup.addView(demoSubview2, p2); DemoButton btn1 = new DemoButton(this); btn1.setText("run Scroller in viewGroup"); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mScrollerViewGroup.startScroll(-10, -100,- 200, -300, 1000); new Thread(){ public void run() { while(mScrollerViewGroup.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。 { Log.i("scroller", "getCurrX()= "+mScrollerViewGroup.getCurrX()+" getCurrY()="+mScrollerViewGroup.getCurrY()); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } }); demoSubview1.addView(btn1); DemoButton btn2 = new DemoButton(this); btn2.setText("run Scroller in view"); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mScrollerView.startScroll(-10, -100,- 200, -300, 1000); new Thread(){ public void run() { while(mScrollerView.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。 { Log.i("scroller", "getCurrX()= "+mScrollerView.getCurrX()+" getCurrY()="+mScrollerView.getCurrY()); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } }); demoSubview2.addView(btn2); } class DemoButton extends Button { public DemoButton(Context ctx) { super(ctx); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i("DemoButton", "------ onDraw------"); } public void computeScroll() { Log.i("DemoButton", " --------------------computeScroll-----------"); // Log.i(TAG, "getCurrX = " + mScroller.getCurrX()); if (mScrollerView.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。 { // 因为调用computeScroll函数的是MyLinearLayout实例, // 所以调用scrollTo移动的将是该实例的孩子,也就是MyButton实例 scrollTo(mScrollerView.getCurrX(), 0); Log.i("DemoButton", "getCurrX = " + mScrollerView.getCurrX()); // 继续让系统重绘 invalidate(); } } } class DemoView extends LinearLayout { public DemoView(Context ctx) { super(ctx); } @Override public void computeScroll() { Log.i("DemoView", " DemoView --------------------computeScroll-----------"); if (mScrollerViewGroup.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。 { // 因为调用computeScroll函数的是MyLinearLayout实例, // 所以调用scrollTo移动的将是该实例的孩子,也就是MyButton实例 scrollTo(mScrollerViewGroup.getCurrX(), 0); Log.i("DemoView", "getCurrX = " + mScrollerViewGroup.getCurrX()); // 继续让系统重绘 getChildAt(0).invalidate(); } } } class DemoViewGroup extends LinearLayout { public DemoViewGroup(Context ctx) { super(ctx); } @Override protected void dispatchDraw(Canvas canvas) { Log.i("DemoViewGroup", "contentview dispatchDraw"); super.dispatchDraw(canvas); } } }
运行程序效果:
点击第一个button后,日志如下:
引用
05-02 13:38:02.291: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:38:02.291: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:38:02.301: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:38:02.311: I/DemoButton(332): ------ onDraw------
05-02 13:38:02.311: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:38:02.311: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:38:02.311: I/DemoButton(332): ------ onDraw------
05-02 13:39:50.432: I/scroller(332): getCurrX()= -11 getCurrY()=-101</b> 05-02 13:39:50.432: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:50.432: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:39:50.432: I/DemoView(332): getCurrX = -12
05-02 13:39:50.442: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:39:50.442: I/DemoButton(332): ------ onDraw------
......................<b>此处省略部分日志</b>...................................................
05-02 13:39:51.412: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:51.412: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:39:51.412: I/DemoView(332): getCurrX = -210
05-02 13:39:51.412: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:39:51.422: I/DemoButton(332): ------ onDraw------
05-02 13:39:51.432: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:51.432: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:39:51.432: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:39:51.432: I/DemoButton(332): ------ onDraw------
05-02 13:38:02.291: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:38:02.301: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:38:02.311: I/DemoButton(332): ------ onDraw------
05-02 13:38:02.311: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:38:02.311: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:38:02.311: I/DemoButton(332): ------ onDraw------
05-02 13:39:50.432: I/scroller(332): getCurrX()= -11 getCurrY()=-101</b> 05-02 13:39:50.432: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:50.432: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:39:50.432: I/DemoView(332): getCurrX = -12
05-02 13:39:50.442: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:39:50.442: I/DemoButton(332): ------ onDraw------
......................<b>此处省略部分日志</b>...................................................
05-02 13:39:51.412: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:51.412: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:39:51.412: I/DemoView(332): getCurrX = -210
05-02 13:39:51.412: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:39:51.422: I/DemoButton(332): ------ onDraw------
05-02 13:39:51.432: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:51.432: I/DemoView(332): DemoView --------------------computeScroll------
05-02 13:39:51.432: I/DemoButton(332): --------------------computeScroll-----------
05-02 13:39:51.432: I/DemoButton(332): ------ onDraw------
通过日志,看出什么了没?
另外,通过该日志,你了解了view的绘画机制没,应该能发现吧。
最终的效果图片:
点击buttom2,日志就不给出了,效果图片如下:
button内的文字移动到了不可见处,
所以调用scrollTo移动的将是该view的内容,如果是viewGroup的话,就移动了它的孩子view了
所以调用scrollTo移动的将是该实例的孩子,也就是MyButton实例
这会儿明白了没?
后面我会尝试的自己模拟一个scrolelr,其实他的作用就是存储一些基本的数值,其他的啥也没做,也和view没有真正关系的,它只是被动的被调用的
发表评论
-
带你深入理解 FLUTTER 中的字体“冷”知识
2020-08-10 23:40 612本篇将带你深入理解 Flutter 开发过程中关于字体和文 ... -
Flutter -自定义日历组件
2020-03-01 17:56 1087颜色文件和屏幕适配的文件 可以自己给定 import ... -
Dart高级(一)——泛型与Json To Bean
2020-02-23 19:13 977从 Flutter 发布到现在, 越来越多人开始尝试使用 Da ... -
flutter loading、Progress进度条
2020-02-21 17:03 1132Flutter Progress 1 条形无固定值进度条 ... -
Flutter使用Https加载图片
2020-02-21 01:39 983Flutter使用Https加载图片 使用http加载图片出 ... -
flutter shared_preferences 异步变同步
2020-02-21 00:55 827前言 引用 在开发原生iOS或Native应用时,一般有判断上 ... -
Flutter TextField边框颜色
2020-02-19 21:31 911监听要销毁 myController.dispose(); T ... -
flutter Future的正确用法
2020-02-18 21:55 788在flutter中经常会用到异步任务,dart中异步任务异步处 ... -
记一次Flutter简单粗暴处理HTTPS证书检验方法
2020-02-18 14:13 921最近在做Flutter项目到了遇到一个无解的事情,当使用Ima ... -
flutter 获取屏幕宽度高度 通知栏高度等屏幕信息
2019-07-27 08:39 1307##MediaQuery MediaQuery.of(con ... -
关于flutter RefreshIndicator扩展listview下拉刷新的问题
2019-07-10 19:40 1058当条目过少时listview某些嵌套情况下可能不会滚动(条目 ... -
flutter listview 改变状态的时候一直无限添加
2019-07-10 16:01 721setstate的时候会一直无限的调用listview.bui ... -
Flutter Android端启动白屏问题的解决
2019-07-09 00:51 1478问题描述 Flutter 应用在 Android 端上启动时 ... -
Flutter中SnackBar使用
2019-07-08 23:43 742底部弹出,然后在指定时间后消失。 注意: build(Bui ... -
Flutter 之点击空白区域收起键盘
2019-07-08 18:43 1758点击空白处取消TextField焦点这个需求是非常简单的,在学 ... -
Flutter 弹窗 Dialog ,AlertDialog,IOS风格
2019-07-08 18:04 1349import 'package:flutter/mate ... -
flutter ---TextField 之 输入类型、长度限制
2019-07-08 14:30 2288TextField想要实现输入类型、长度限制需要先引入impo ... -
【flutter 溢出BUG】键盘上显示bottom overflowed by 104 PIXELS
2019-07-08 11:13 1520一开始直接使用Scaffold布局,body:new Colu ... -
解决Flutter项目卡在Initializing gradle...界面的问题
2019-07-07 12:53 842Flutter最近很火,我抽出了一点时间对Flutter进行了 ... -
关于android O 上 NotificationChannel 的一些注意事项
2019-07-04 11:47 921最近在适配android O,遇到个问题,应用中原本有设置界面 ...
相关推荐
在Android开发中,`Scroller`是一个非常重要的工具类,主要用于实现平滑的滚动效果。它并不直接控制View的移动,而是提供一个离散的、可...理解并熟练掌握`Scroller`的使用,对于提升Android应用的用户体验至关重要。
本示例“android scroller学习demo”将带你深入理解如何利用`Scroller`实现类似QQ ListView的侧滑删除效果。下面我们将详细探讨`Scroller`的工作原理以及如何在实际项目中应用它。 `Scroller`并非一个视图控件,...
总结,`Scroller`是Android中实现平滑滚动效果的重要工具,通过合理的使用和定制,我们可以创造出丰富多样的滚动动画。理解其工作原理并结合`Interpolator`,可以提升用户界面的交互体验。在实际项目中,应根据需求...
通过分析该项目的代码,可以更深入地理解Scroller的工作原理和使用方法。 总之,Scroller是Android中实现平滑滚动动画的一个高效工具,它允许开发者自定义滚动速度和时间,从而创建出各种定制化的滚动效果。通过...
Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,项目详情http://blog.csdn.net/xiaanming/article/details/17539199
在Android开发中,`Scroller`是一个非常重要的组件,它主要用于处理平滑的滚动效果,尤其是在没有用户交互的情况下。在本篇文章中,我们将深入探讨`Scroller`的工作原理,以及如何在实际应用中使用它来实现平滑滚动...
Android Scroller是Android系统中用于实现平滑滚动效果的重要组件,它主要用于控制View或者 ViewGroup的动画滚动效果,比如ScrollView、...理解和熟练运用Scroller,对于提升Android应用的用户体验至关重要。
通过这个练习,你可以深入理解`Scroller`的工作原理,以及如何与自定义View配合实现复杂的滑动效果。同时,这也是提升Android开发技能的一个好方法,因为你将直接与Android的绘制机制打交道,对View的生命周期和触摸...
首先,理解`Scroller`的工作原理是关键。`Scroller`并不直接改变View的位置,而是通过计算出一系列连续的坐标点,这些坐标点代表了滚动过程中的位置变化。开发者需要在`onDraw()`或`computeScroll()`方法中获取当前...
总的来说,`Scroller`是Android中实现平滑滚动效果的重要工具,理解其工作原理和使用方法对于提升用户体验至关重要。通过合理地利用`Scroller`,我们可以为用户创造出更加流畅、自然的交互体验。
在Android开发中,`Scroller`...理解并熟练掌握`Scroller`的使用,能帮助开发者创造出更加流畅和自然的用户界面。在`MyScroller`这个Demo中,你可以看到如何将理论知识转化为实际应用,进一步加深对`Scroller`的理解。
Scroller在Android中是一个核心组件,它主要用于实现View的平滑滚动效果,使得视图能够按照预设的时间和轨迹进行连续、平滑的移动,而不是简单地瞬移。Scroller本身并不直接改变View的位置,而是提供计算滚动过程的...
Android事件拦截机制 Android中事件的传递和拦截和View树结构是相关联的,在View树中,分为叶子节点和普通节点,普通节点有子节点只能是ViewGroup,叶子节点可以是View或者ViewGroup。Android和事件分发拦截相关的...
在Android开发中,动画效果是提升用户体验的...理解`Scroller`的工作原理和使用方式对于开发流畅的滚动界面和动画至关重要。在实际项目中,`Scroller`通常与`View`的滚动方法结合使用,创造出更加丰富的用户交互体验。
本文实例为大家分享了Android使用Scroller实现弹性滑动展示的具体代码,供大家参考,具体内容如下 scrollTo、scrollBy View内部为了实现滑动提供了这两个方法,但是使用这两个方法滑动的效果是瞬间的不够平滑,如何...
首先,我们要理解Scroller在Android中的作用。Scroller并非一个View或者ViewGroup,而是一个辅助类,用于处理平滑滚动的动画效果。它不直接绘制视图,而是提供计算下一帧位置的方法,供ViewGroup在滑动过程中调用。...
结合提供的文件列表,这个"Scroller使用demo"项目可能包含了一个简单的Android应用,演示了如何在自定义View中使用`Scroller` 来实现平滑的滑动效果。通过阅读`build.gradle` 文件可以了解项目的构建依赖,`README....
在Android开发中,`Scroller`和`computeScroll`是两个关键的概念,它们与ViewGroup的滚动动画密切相关。本文将详细解析这两个概念及其调用机制之间的关系。 首先,`Scroller`是一个内部类,它并不直接参与ViewGroup...