以上就是给各位分享AndroidViewPager+轮播图,android开发应用实战详解,其中也会对android轮播图实现进行解释,同时本文还将给你拓展AndroidRollPagerView实现
以上就是给各位分享Android ViewPager+轮播图,android开发应用实战详解,其中也会对android轮播图实现进行解释,同时本文还将给你拓展Android RollPagerView实现轮播图、Android Studio 3.4.1中使用com.android.support.v4.view.ViewPager提示不存在该类或程序闪退、Android View 绘制流程之 DecorView 与 ViewRootImpl Android View 绘制流程之 DecorView 与 ViewRootImplAndroid View 的绘制流程之 Measure 过程详解 (一)Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)Android View 的事件分发原理解析Android 自定义 View 详解Android View 的测量流程详解、Android ViewPager等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:- Android ViewPager+轮播图,android开发应用实战详解(android轮播图实现)
- Android RollPagerView实现轮播图
- Android Studio 3.4.1中使用com.android.support.v4.view.ViewPager提示不存在该类或程序闪退
- Android View 绘制流程之 DecorView 与 ViewRootImpl Android View 绘制流程之 DecorView 与 ViewRootImplAndroid View 的绘制流程之 Measure 过程详解 (一)Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)Android View 的事件分发原理解析Android 自定义 View 详解Android View 的测量流程详解
- Android ViewPager
Android ViewPager+轮播图,android开发应用实战详解(android轮播图实现)
v.setBackgroundResource(R.drawable.indicator_selected);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(UIUtils.dip2px(6), UIUtils.dip2px(6));// dp
// -->
// px
if (i != 0) {
params.leftMargin = UIUtils.dip2px(8);
params.bottomMargin = UIUtils.dip2px(8);
} else {
v.setBackgroundResource(R.drawable.indicator_normal);// 设置默认选中
}
mPointContainer.addView(v, params);
5.2 MAX_VALUE / 3、middle % 3
表示第一个小黑点是默认的
// 给ViewPager设置中间选中的值
int middle = Integer.MAX_VALUE / 3;
int extra = middle % 3;
mViewPaper.setCurrentItem(middle - extra);
5.3 轮播图延迟时间,看看下面理解
//自动播放广告栏任务
class AutoSwitchTask implements Runnable {
// 开始轮播
public void start() {
stop();
UIUtils.postDelayed(this, 10000);//“10000”表示轮播图的第一图片开始延迟时间后轮播
}
// 停止轮播
public void stop() {
UIUtils.removeCallbacks(this);
}
@Override
public void run() {
// 让ViewPager选中下一个
int item = mViewPaper.getCurrentItem();
mViewPaper.setCurrentItem(++item);
UIUtils.postDelayed(this, 5000);//“5000”表示每一个图片延迟时间后轮播
}
}
5.4 给容器添加三个轮播图,看看下面理解
@Override
public Object instantiateItem(ViewGroup container, int position) {
position = position % 3;//三个轮播图
ImageView iv = new ImageView(MainActivity.this);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
// 给iv设置数据
iv.setimageResource(R.drawable.image1);// 设置默认图片
// 设置网络图片
if (position == 0) {
iv.setimageResource(R.drawable.image1);//第一个轮播图
// BitmapHelper.display(iv,R.drawable.image1 );
} else if (position == 1){
iv.setimageResource(R.drawable.image2);//第二个轮播图
}else {
iv.setimageResource(R.drawable.image3);//第三个轮播图
}
// BitmapHelper.display(iv, AppConfig.IMAGE_BASE_UR
final int finalPosition = position;
iv.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
roastingPictureClick(finalPosition);
}
});
// 给viewpager加视图
container.addView(iv);
return iv;
}
5.5 轮播图点击事件,代码如下:
//轮播图点击
private void roastingPictureClick(int position) {
Toast.makeText(this, “轮播图点击:” + position, Toast.LENGTH_SHORT).show();
}
5.6 三个小点,一个小黑点,二个小白点
@Override
public void onPageSelected(int position) {
// 页面选中时
position = position % 3;
int count = mPointContainer.getChildCount();
for (int i = 0; i < count; i++) {
View view = mPointContainer.getChildAt(i);
ublic void onPageSelected(int position) {
// 页面选中时
position = position % 3;
int count = mPointContainer.getChildCount();
for (int i = 0; i < count; i++) {
View view = mPointContainer.getChildAt(i);
Android RollPagerView实现轮播图
Android RollPagerView实现轮播图
android图片轮播效果,RollViewPager的简单使用
<com.jude.rollviewpager.RollPagerView android:id="@+id/mViewPager" android:layout_width="match_parent" android:layout_height="170dp" app:rollviewpager_play_delay="3000" />
在build.gradle(app)加载包
compile 'com.jude:rollviewpager:1.2.9'
实现代码:
//广告轮播 mViewPager = (RollPagerView) ItemView.findViewById(R.id.mViewPager); mViewPager.setAdapter(new ImageLoopAdapter(getActivity(),mViewPager));
// ImageLoopAdapter.java public class ImageLoopAdapter extends LoopPagerAdapter { String[] imgs = new String[0]; private Context mContext; public ImageLoopAdapter(Context mContext,RollPagerView viewPager) { super(viewPager); this.mContext = mContext; } @Override public View getView(ViewGroup container,int position) { ImageView view = new ImageView(container.getContext()); view.setScaleType(ImageView.ScaleType.CENTER_CROP); view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)); Glide.with(mContext).load(Constants.URL[position]).into(view); return view; } @Override public int getRealCount() { return Constants.URL.length; } }
添加图片数据源:
这里可以自己设定
public class Constants { public static String[] URL = { "http://cdn-l.llsapp.com/connett/c3115411-3669-466d-8ef2-e6c42c690303","http://7xjww9.com1.z0.glb.clouddn.com/Hopetoun_falls.jpg","http://cdn.llsapp.com/crm_test_1449051526097.jpg",}; }
以上就是Android 实现轮播图的实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
Android Studio 3.4.1中使用com.android.support.v4.view.ViewPager提示不存在该类或程序闪退
本文链接:https://blog.csdn.net/Marco_L/article/details/95097518
在编写这段代码的时候你会发现输入时并没有任何关于类的选择提示,但是全部打完后编译可以通过(细心的话回发现在右侧proview中会有错误提示,如下)。
但是!!!!程序运行后会闪退
从网上搜了很多资料,大部分都是针对eclipse的,并且少数关于Android Studio的根本没有效果。后来无意间看到Android Studio在新的版本中对android.support中的内容进行了更新。
com.android.support.v4.view.ViewPager
变成了
androidx.viewpager.widget.ViewPager 程序可以正常运行。
其他变动请参照:
https://blog.csdn.net/yin_ol/article/details/89421390
如有其他未列出的依赖,请参考 https://developer.android.google.cn/topic/libraries/support-library/refactor
Android View 绘制流程之 DecorView 与 ViewRootImpl Android View 绘制流程之 DecorView 与 ViewRootImplAndroid View 的绘制流程之 Measure 过程详解 (一)Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)Android View 的事件分发原理解析Android 自定义 View 详解Android View 的测量流程详解
一年多以前,曾经以为自己对 View 的添加显示逻辑已经有所了解了,事后发现也只是懂了些皮毛而已。经过一年多的实战,Android 和 Java 基础都有了提升,是时候该去看看 DecorView 的添加显示。
View 的绘制系列文章:
-
Android View 绘制流程之 DecorView 与 ViewRootImpl
-
Android View 的绘制流程之 Measure 过程详解 (一)
-
Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)
-
Android View 的事件分发原理解析
-
Android 自定义 View 详解
概论
Android 中 Activity 是作为应用程序的载体存在,代表着一个完整的用户界面,提供了一个窗口来绘制各种视图,当 Activity 启动时,我们会通过 setContentView 方法来设置一个内容视图,这个内容视图就是用户看到的界面。那么 View 和 activity 是如何关联在一起的呢 ?
上图是 View 和 Activity 之间的关系。先解释图中一些类的作用以及相关关系:
-
Activity : 对于每一个 activity 都会有拥有一个 PhoneWindow。
- PhoneWindow :该类继承于 Window 类,是 Window 类的具体实现,即我们可以通过该类具体去绘制窗口。并且,该类内部包含了一个 DecorView 对象,该 DectorView 对象是所有应用窗口的根 View。
-
DecorView 是一个应用窗口的根容器,它本质上是一个 FrameLayout。DecorView 有唯一一个子 View,它是一个垂直 LinearLayout,包含两个子元素,一个是 TitleView( ActionBar 的容器),另一个是 ContentView(窗口内容的容器)。
-
ContentView :是一个 FrameLayout(android.R.id.content),我们平常用的 setContentView 就是设置它的子 View 。
- WindowManager : 是一个接口,里面常用的方法有:添加View,更新View和删除View。主要是用来管理 Window 的。WindowManager 具体的实现类是WindowManagerImpl。最终,WindowManagerImpl 会将业务交给 WindowManagerGlobal 来处理。
- WindowManagerService (WMS) : 负责管理各 app 窗口的创建,更新,删除, 显示顺序。运行在 system_server 进程。
ViewRootImpl :拥有 DecorView 的实例,通过该实例来控制 DecorView 绘制。ViewRootImpl 的一个内部类 W,实现了 IWindow 接口,IWindow 接口是供 WMS 使用的,WSM 通过调用 IWindow 一些方法,通过 Binder 通信的方式,最后执行到了 W 中对应的方法中。同样的,ViewRootImpl 通过 IWindowSession 来调用 WMS 的 Session 一些方法。Session 类继承自 IWindowSession.Stub
,每一个应用进程都有一个唯一的 Session 对象与 WMS 通信。
DecorView 的创建
先从 Mainactivity 中的代码看起,首先是调用了 setContentView;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
该方法是父类 AppCompatActivity 的方法,最终会调用 AppCompatDelegateImpl 的 setContentView 方法:
// AppCompatDelegateImpl
public void setContentView(int resId) { this.ensureSubDecor(); ViewGroup contentParent = (ViewGroup)this.mSubDecor.findViewById(16908290); contentParent.removeAllViews(); LayoutInflater.from(.mContext).inflate(resId,contentParent); .mOriginalWindowCallback.onContentChanged(); }
ensureSubDecor 从字面理解就是创建 subDecorView,这个是根据主题来创建的,下文也会讲到。创建完以后,从中获取 contentParent,再将从 activity 传入的 id xml 布局添加到里面。不过大家注意的是,在添加之前先调用 removeAllViews() 方法,确保没有其他子 View 的干扰。
private ensureSubDecor() { if (!.mSubDecorInstalled) { this.mSubDecor = .createSubDecor(); ...... } ...... }
最终会调用 createSubDecor() ,来看看里面的具体代码逻辑:
private ViewGroup createSubDecor() { // 1、获取主题参数,进行一些设置,包括标题,actionbar 等 TypedArray a = .mContext.obtainStyledAttributes(styleable.AppCompatTheme); a.hasValue(styleable.AppCompatTheme_windowActionBar)) { a.recycle(); throw new IllegalStateException("You need to use a Theme.AppCompat theme (or descendant) with this activity."); } else { if (a.getBoolean(styleable.AppCompatTheme_windowNoTitle,false)) { this.requestwindowFeature(1); } else if (a.getBoolean(styleable.AppCompatTheme_windowActionBar,1)">this.requestwindowFeature(108); } if (a.getBoolean(styleable.AppCompatTheme_windowActionBarOverlay,1)">this.requestwindowFeature(109if (a.getBoolean(styleable.AppCompatTheme_windowActionModeOverlay,1)">this.requestwindowFeature(10this.mIsFloating = a.getBoolean(styleable.AppCompatTheme_android_windowIsFloating,1)">); a.recycle(); 2、确保优先初始化 DecorView .mWindow.getDecorView(); LayoutInflater inflater = LayoutInflater.from(.mContext); ViewGroup subDecor = null; 3、根据不同的设置来对 subDecor 进行初始化 .mWindowNoTitle) { if (.mIsFloating) { subDecor = (ViewGroup)inflater.inflate(layout.abc_dialog_title_material,(ViewGroup)); this.mHasActionBar = this.mOverlayActionBar = ; } .mHasActionBar) { TypedValue outValue = new TypedValue(); this.mContext.getTheme().resolveAttribute(attr.actionBarTheme,outValue,1)">true); Object themedContext; if (outValue.resourceId != 0) { themedContext = new ContextThemeWrapper(.mContext,outValue.resourceId); } { themedContext = .mContext; } subDecor = (ViewGroup)LayoutInflater.from((Context)themedContext).inflate(layout.abc_screen_toolbar,1)">this.mDecorContentParent = (DecorContentParent)subDecor.findViewById(id.decor_content_parent); this.mDecorContentParent.setwindowCallback(.getwindowCallback()); .mOverlayActionBar) { this.mDecorContentParent.initFeature(109); } .mFeatureProgress) { this.mDecorContentParent.initFeature(2.mFeatureIndeterminateProgress) { this.mDecorContentParent.initFeature(5); } } } { .mOverlayActionMode) { subDecor = (ViewGroup)inflater.inflate(layout.abc_screen_simple_overlay_action_mode,1)">); } { subDecor = (ViewGroup)inflater.inflate(layout.abc_screen_simple,1)">); } if (VERSION.SDK_INT >= 21) { ViewCompat.setonApplyWindowInsetsListener(subDecor, OnApplyWindowInsetsListener() { public WindowInsetsCompat onApplyWindowInsets(View v,WindowInsetsCompat insets) { int top = insets.getSystemWindowInsetTop(); int newTop = AppCompatDelegateImpl..updateStatusGuard(top); if (top != newTop) { insets = insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(),newTop,insets.getSystemWindowInsetRight(),insets.getSystemWindowInsetBottom()); } return ViewCompat.onApplyWindowInsets(v,insets); } }); } { ((FitwindowsViewGroup)subDecor).setonFitSystemWindowsListener( OnFitSystemWindowsListener() { onFitSystemWindows(Rect insets) { insets.top = AppCompatDelegateImpl..updateStatusGuard(insets.top); } }); } } if (subDecor == ) { new IllegalArgumentException("AppCompat does not support the current theme features: { windowActionBar: " + this.mHasActionBar + ",windowActionBarOverlay: " + this.mOverlayActionBar + ",android:windowIsFloating: " + this.mIsFloating + ",windowActionModeOverlay: " + this.mOverlayActionMode + ",windowNoTitle: " + this.mWindowNoTitle + " }"this.mDecorContentParent == ) { this.mTitleView = (TextView)subDecor.findViewById(id.title); } ViewUtils.makeOptionalFitsSystemWindows(subDecor); ContentFrameLayout contentView = (ContentFrameLayout)subDecor.findViewById(id.action_bar_activity_content); ViewGroup windowContentView = (ViewGroup)this.mWindow.findViewById(16908290); if (windowContentView != while(windowContentView.getChildCount() > 0) { View child = windowContentView.getChildAt(0); windowContentView.removeViewAt(0); contentView.addView(child); } windowContentView.setId(-1); contentView.setId(16908290if (windowContentView instanceof FrameLayout) { ((FrameLayout)windowContentView).setForeground((Drawable)); } } 将 subDecor 添加到 DecorView 中 .mWindow.setContentView(subDecor); contentView.setAttachListener( OnAttachListener() { onAttachedFromWindow() { } onDetachedFromWindow() { AppCompatDelegateImpl..dismisspopups(); } }); subDecor; } } }
上面的代码总结来说就是在做一件事,就是创建 subDecor。摊开来说具体如下:
1、根据用户选择的主题来设置一些显示特性,包括标题,actionbar 等。
2、根据不同特性来初始化 subDecor;对 subDecor 内部的子 View 进行初始化。
3、最后添加到 DecorView中。
添加的具体代码如下:此处是通过调用
// AppCompatDelegateImpl
this.mWindow.getDecorView();
// phoneWindow
public final View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
installDecor();
}
return mDecor;
}
void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
// 生成 DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
// 这样 DecorView 就持有了window
mDecor.setwindow(this);
}
......
}
protected DecorView generateDecor(int featureId) {
// System process doesn''t have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context,so we don''t cling to the
// activity.
Context context;
if (mUseDecorContext) {
Context applicationContext = getContext().getApplicationContext();
if (applicationContext == null) {
context = getContext();
} else {
context = new DecorContext(applicationContext,getContext());
if (mTheme != -1) {
context.setTheme(mTheme);
}
}
} else {
context = getContext();
}
return new DecorView(context,featureId,this,getAttributes());
}
到此,DecorView 的创建就讲完了。可是我们似乎并没有看到 DecorView 是被添加的,什么时候对用户可见的。
WindowManager
View 创建完以后,那 Decorview 是怎么添加到屏幕中去的呢?当然是 WindowManager 呢,那么是如何将 View 传到 WindowManager 中呢。
看 ActivityThread 中的 handleResumeActivity 方法:
// ActivityThread
public void handleResumeActivity(IBinder token,1)">boolean finalStateRequest,1)">boolean isForward,String reason) { ...... final int forwardBit = isForward ? WindowManager.LayoutParams.soFT_INPUT_IS_FORWARD_NAVIGATION : 0; If the window hasn''t yet been added to the window manager,1)"> and this guy didn''t finish itself or start another activity,1)"> then go ahead and add the window. boolean willBeVisible = !a.mStartedActivity; willBeVisible) { try { willBeVisible = ActivityManager.getService().willActivityBeVisible( a.getActivityToken()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } } if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getwindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getwindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; ...... if (a.mVisibleFromClient) { a.mWindowAdded) { a.mWindowAdded = ; wm.addView(decor,l); } { The activity will get a callback for this {@link LayoutParams} change earlier. However,at that time the decor will not be set (this is set in this method),so no action will be taken. This call ensures the callback occurs with the decor set. a.onWindowAttributesChanged(l); } } If the window has already been added,but during resume we started another activity,then don''t yet make the window visible. } if (localLOGV) Slog.v(TAG,"Launch " + r + " mStartedActivity set"); r.hideForNow = ; } Get rid of anything left hanging around. cleanUpPendingRemoveWindows(r,1)">false /* force */); The window is Now visible if it has been added,we are not simply finishing,and we are not starting another activity. if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { if (r.newConfig != ) { performConfigurationChangedForActivity(r,r.newConfig); (DEBUG_CONfigURATION) { Slog.v(TAG,"Resuming activity " + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig); } r.newConfig = ; }isForward); WindowManager.LayoutParams l = r.window.getAttributes(); ((l.softInputMode & WindowManager.LayoutParams.soFT_INPUT_IS_FORWARD_NAVIGATION) != forwardBit) { l.softInputMode = (l.softInputMode & (~WindowManager.LayoutParams.soFT_INPUT_IS_FORWARD_NAVIGATION)) | forwardBit; (r.activity.mVisibleFromClient) { ViewManager wm = a.getwindowManager(); View decor = r.window.getDecorView(); wm.updateViewLayout(decor,l); } } r.activity.mVisibleFromServer = ; mNumVisibleActivities++ (r.activity.mVisibleFromClient) { 这里也会调用addview r.activity.makeVisible(); } } r.nextIdle = mNewActivities; mNewActivities = r; r); Looper.myQueue().addIdleHandler( Idler()); }
上面的代码主要做了以下几件事:
1、获取到 DecorView,设置不可见,然后通过 wm.addView(decor,l) 将 view 添加到 WindowManager;
2、在某些情况下,比如此时点击了输入框调起了键盘,就会调用 wm.updateViewLayout(decor,l) 来更新 View 的布局。
3、这些做完以后,会调用 activity 的 makeVisible ,让视图可见。如果此时 DecorView 没有添加到 WindowManager,那么会添加。
// Activity
makeVisible() { mWindowAdded) { ViewManager wm = getwindowManager(); wm.addView(mDecor,getwindow().getAttributes()); mWindowAdded = ; } mDecor.setVisibility(View.VISIBLE); }
接下来,看下 addview 的逻辑。 WindowManager 的实现类是 WindowManagerImpl,而它则是通过 WindowManagerGlobal 代理实现 addView 的,我们看下 addView 的方法:
WindowManagerGlobal addView(View view,ViewGroup.LayoutParams params,display display,Window parentwindow) { ...... root = ViewRootImpl(view.getContext(),display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); do this last because it fires off messages to start doing things { root.setView(view,wparams,panelParentView); } (RuntimeException e) { BadTokenException or InvaliddisplayException,clean up. if (index >= 0) { removeViewLocked(index,1)">); } e; } }
在这里,实例化了 ViewRootImpl 。同时调用 ViewRootImpl 的 setView 方法来持有了 DecorView。此外这里还保存了 DecorView ,Params,以及 ViewRootImpl 的实例。
现在我们终于知道为啥 View 是在 OnResume 的时候可见的呢。
ViewRootImpl
实际上,View 的绘制是由 ViewRootImpl 来负责的。每个应用程序窗口的 DecorView 都有一个与之关联的 ViewRootImpl 对象,这种关联关系是由 WindowManager 来维护的。
先看 ViewRootImpl 的 setView 方法,该方法很长,我们将一些不重要的点注释掉:
/** * We have one child */ setView(View view,WindowManager.LayoutParams attrs,View panelParentView) { synchronized () { if (mView == ) { mView = view; ...... mAdded = ; int res; = WindowManagerImpl.ADD_OKAY; */ Schedule the first layout -before- adding to the window manager,to make sure we do the relayout before receiving any other events from the system. requestLayout(); ...... } } }
这里先将 mView 保存了 DecorView 的实例,然后调用 requestLayout() 方法,以完成应用程序用户界面的初次布局。
requestLayout() { mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = ; scheduleTraversals(); } }
因为是 UI 绘制,所以一定要确保是在主线程进行的,checkThread 主要是做一个校验。接着调用 scheduleTraversals 开始计划绘制了。
scheduleTraversals() { mTraversalScheduled) { mTraversalScheduled = ; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable,1)">); mUnbufferedInputdispatch) { scheduleConsumeBatchedinput(); } notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } }
这里主要关注两点:
mTraversalBarrier : Handler 的同步屏障。它的作用是可以拦截 Looper 对同步消息的获取和分发,加入同步屏障之后,Looper 只会获取和处理异步消息,如果没有异步消息那么就会进入阻塞状态。也就是说,对 View 绘制渲染的处理操作可以优先处理(设置为异步消息)。
mChoreographer: 编舞者。统一动画、输入和绘制时机。也是这章需要重点分析的内容。
mTraversalRunnable :TraversalRunnable 的实例,是一个Runnable,最终肯定会调用其 run 方法:
class TraversalRunnable implements Runnable { @Override run() { doTraversal(); } }
doTraversal,如其名,开始绘制了,该方法内部最终会调用 performTraversals 进行绘制。
doTraversal() { (mTraversalScheduled) { mTraversalScheduled = ; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); (mProfile) { Debug.startMethodTracing("ViewAncestor"); } performTraversals(); (mProfile) { Debug.stopMethodTracing(); mProfile = ; } } }
到此,DecorView 与 activity 之间的绑定关系就讲完了,下一章,将会介绍 performTraversals 所做的事情,也就是 View 绘制流程。
附上一张流程图:
到此,DecorView 与 ViewRootImpl 之间的关系就讲的很清楚了。
点击查看下一篇 Android View 的测量流程详解
总结
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
Android ViewPager
ViewPager
使用范围:导航、菜单
功能:可以使视图滑动,类似于 Lanucher 左右滑动
需要配置器 PagerAdapter
参考文献:http://blog.csdn.net/alangdangjia/article/details/9054921
实现步骤:3 步
1. 向布局文件中添加 android.support.v4.view.ViewPager 组件
这个组件,注意这个组件是用来显示左右滑动的界面的,如果不加载 xml 布局文件,他是不会显示内容的。
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" >
2. 加载显示页卡
LayoutInflater lf = getLayoutInflater().from(this);
view1 = lf.inflate(R.layout.layout1, null);
view2 = lf.inflate(R.layout.layout2, null);
view3 = lf.inflate(R.layout.layout3, null);
// 将要分页显示的View装入数组中
List<View> viewList = new ArrayList<View>();
viewList.add(view1);
viewList.add(view2);
viewList.add(view3);
3. 在 activity 中实例化 ViewPager 组件,重写 PageAdapter 与 ListAdapter 类似。
重写方法有两种:创建 PagesAdapter 对象,重新创建类继承 PageAdapter。
其中必须覆盖以下方法:
instantiateItem(ViewGroup, int)
destroyItem(ViewGroup, int, Object)
getCount()
isViewFromObject(View, Object)
关于Android ViewPager+轮播图,android开发应用实战详解和android轮播图实现的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Android RollPagerView实现轮播图、Android Studio 3.4.1中使用com.android.support.v4.view.ViewPager提示不存在该类或程序闪退、Android View 绘制流程之 DecorView 与 ViewRootImpl Android View 绘制流程之 DecorView 与 ViewRootImplAndroid View 的绘制流程之 Measure 过程详解 (一)Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)Android View 的事件分发原理解析Android 自定义 View 详解Android View 的测量流程详解、Android ViewPager的相关信息,请在本站寻找。
本文标签: