1.extends linearLayout 继承想要用的布局,首先完成布局的填充在 onFinishInflate 方法中 findViewById();
@Override protected void onFinishInflate() { super.onFinishInflate(); mTop = findViewById(R.id.id_stickynavlayout_topview); mNav = findViewById(R.id.id_stickynavlayout_indicator); View view = findViewById(R.id.id_stickynavlayout_viewpager); if (!(view instanceof ViewPager)) { throw new RuntimeException( "id_stickynavlayout_viewpager show used by ViewPager !"); } mViewPager = (ViewPager) view; } 2.测量布局 在onMeasuer 方法中实现,根据不同的要求进行不同的测量,基本绘制用到的四个方法
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //onMeasure //不限制顶部的高度 super.onMeasure(widthMeasureSpec, heightMeasureSpec); getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); ViewGroup.LayoutParams params = mViewPager.getLayoutParams(); params.height = getMeasuredHeight() - mNav.getMeasuredHeight(); setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight() + mNav.getMeasuredHeight() + mViewPager.getMeasuredHeight()); } 1.在onMeasure中要注意通过setMeasuredDimension(width, height)保存计算结果 2.//UNSPECIFIED //Measure specification mode: The parent has not imposed any constraint //on the child. It can be whatever size it wants. //测量规范模式:父没有对孩子施加任何约束。它可以是它想要的大小 //EXACTLY //Measure specification mode: The parent has determined an exact size //for the child. The child is going to be given those bounds regardless //of how big it wants to be //测量规范模式:父已确定一个确切的大小*为孩子。不管孩子有多大,他们都将被赋予这些 //Measure specification mode: The child can be as large as it wants up //to the specified size //测量规格模式:孩子可以大,因为它想*到指定的大小
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //onLayout super.onLayout(changed, l, t, r, b); } (1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来; (2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的; public void layout(int l, int t, int r, int b) protected boolean setFrame(int left, int top, int right, int bottom) protected void onLayout(boolean changed, int left, int top, int right, int bottom) layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用 @Override protected void onDraw(Canvas canvas) { //onDraw super.onDraw(canvas); }
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { //onSizeChange super.onSizeChanged(w, h, oldw, oldh); mTopViewHeight = mTop.getMeasuredHeight(); }
ScrollView sc = new ScrollView(getContext()); sc.fling(100); OverScroller os = new OverScroller(getContext()); //fling();滑动多少调用的方法 os.fling(0,0,0,0,0,0,0,0);
@Override public void scrollTo(int x, int y) { //scrollTo 滑动到具体的位置 if (y < 0) { y = 0; } if (y > mTopViewHeight) { y = mTopViewHeight; } if (y != getScrollY()) { super.scrollTo(x, y); } }
重点来了,首先要实现滑动的方法 1.onFinishInflate()在我看来就好像Activity中的Activity();完成一些初使的工作,findViewById(); 2.onMeasure();进行测量,注意MeasureSpec的用法,LayoutParmas的宽高,最后记得setMeasuredDimension()把宽高设置上去 3.onSizeChange(); 一变化的操作都放在这里 4.computeScroll();这个方法会用scrollTo(w,h)到指定的位置 5.onStartNestedScroll();开始滑动 要return true才能滑动部布局 6.onNestedScrollAccepted();就像Activty中的resume,pausee,暂停再次执行会启动该方法 7.onNestedPreScroll();滑动执行的操作每次都会执行 8.scrollTo(); 滑动到哪儿 9.onStopNestedScroll();停止滑动的操作
getScaleY()和getgetScrollY()的区别,在这里踩坑了 indicator的实现逻辑 1.首页得到标题的数据,长度,用代码布局的方式完成布局逻辑 2.用onSizeChange()方法完成数据变化时的上操作 3.用dispathDraw的canvas来完成下划线
三、自定义View增加属性的两种方法:
四、控件绘制 onDraw()
,这篇也是写关于,希望大家能得以帮助, 配合AppBarLayout,Toolbar和TabLayout的使用 ,自己总结关于