类似于ViewPager的效果,子类导航页面可以滑动,当滑动某个子类导航页面,导航线会平滑地向父类导航移动
·添加布局
页面有若干item组成,每个item按样式是一张图片,下面加文字。那据说有一种比较高级的实现方法,就是外边一个TextView,里面添加图片和文字。TextView里面加图片简单,只要添加android:drawableTop="icon的ID",但是这有一个问题,在尝试用drable.setBounds设置图片的宽高的时候,无效。
·在values下添加attrs.xml(自定义属性)
在根布局中添加:
添加布局代码,因为属于ViewPager的滑动页面,所以新建一个fragment_home_nav_program.xml吧
classHomePageNavAdapter:PagerAdapter(){overridefuninstantiateItem(container:ViewGroup,position:Int):Any{//returnsuper.instantiateItem(container,position)when(position){0->{varnavView=LayoutInflater.from(container.context).inflate(R.layout.fragment_home_nav_program,container,false)container.addView(navView)returnnavView}1->{vartextView=TextView(container.context)textView.text="第二页..."container.addView(textView)returntextView}2->{vartextView=TextView(container.context)textView.text="第三页..."container.addView(textView)returntextView}else->{vartextView=TextView(container.context)textView.text="超出范围了"returntextView}}}overridefunisViewFromObject(view:View,`object`:Any):Boolean{returnview==`object`}overridefungetCount():Int{return3}overridefundestroyItem(container:ViewGroup,position:Int,`object`:Any){container.removeView(`object`asView)}}·实现一条导航线跟着Viewpager的页面移动而移动
另一种,简便的方法是实用动画:设置addOnPageChangeListener监听,在onPageScrolled中加入:
varpositionOffsetPd=ScreenDimen.getInstance(context!!).pixToPd(positionOffsetPixels)ViewCompat.animate(homepage_nav_moveLine).translationX(position*screenWidth/3+positionOffsetPd/3+((screenWidth/3-homepage_nav_moveLine.width))/2+10).setDuration(0)在onPageScrollStateChanged中positionOffsetPixels是滑动页面的偏移像素,这里把它转换成dp值。positon是第几页
滑动一次页面,会产生一长串的positionOffsetPixels,系统也会多次调用onPageScrollStateChanged函数,每调用一次,就创建一个duration为0的动画(瞬间跳转,相当于平移)此处疑似有误,ViewCompat.animate(homepage_nav_moveLine).translationX后面接的应该是像素值,所以计算位移直接实用positionOffsetPixels即可,而无需转换为dp值,正确的应该是:
overridefunonPageScrolled(position:Int,positionOffset:Float,positionOffsetPixels:Int){ViewCompat.animate(move_line).translationX(position%3*(screenWidth/3)+positionOffsetPixels/3+(screenWidth/3-move_line.width)/2+0f).setDuration(0)}
·接着要实现滑动子类导航页面时,改变父类导航的字体为加粗
写在onPageSelected,因为这个函数每滑动翻页一次才被调用一次
overridefunonPageSelected(position:Int){homepage_nav_prog.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL))homepage_nav_doc.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL))homepage_nav_source.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL))when(position){0->{homepage_nav_prog.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD))}1->{homepage_nav_doc.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD))}2->{homepage_nav_source.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD))}}}
homepage_nav_prog.setOnClickListener{vp_homePageNav.currentItem=Int.MAX_VALUE/2-Int.MAX_VALUE/2%3}homepage_nav_doc.setOnClickListener{vp_homePageNav.currentItem=Int.MAX_VALUE/2-Int.MAX_VALUE/2%3+1}homepage_nav_source.setOnClickListener{vp_homePageNav.currentItem=Int.MAX_VALUE/2-Int.MAX_VALUE/2%3+2}
另外还有子类导航的点击事件没有设置,但是先就这样吧
源码
其他
通过改变leftMargin值实现线的移动
·当使用homepage_nav_moveLine.layoutParams.leftMargin获取移动线的leftMargin时,提示
cannotinlinebytecidebuiltwithJVMtarget1.8intobytecodethatisbeingbuiltwithJVMtarget1.6
需要在build.grandle中添加
compileOptions{sourceCompatibility=1.8targetCompatibility=1.8}kotlinOptions{jvmTarget="1.8"}·当给它赋值的时候,提示
valcannotbereassigned
查看.leftMargin方法在View类中的定义
inlinevalView.marginLeft:Intget()=(layoutParamsasMarginLayoutParams).leftMargin:0所以只要改成
classScreenDimenprivateconstructor(context:Context){privatevarcontext:Context=nullprivatevarwindowManager:WindowManager=nullprivatevardisplayMetrics:DisplayMetrics=nullinit{windowManager=(context.getSystemService(Context.WINDOW_SERVICE)asWindowManager)displayMetrics=DisplayMetrics()windowManager!!.defaultDisplay.getMetrics(displayMetrics)}companionobject{varinstance:ScreenDimen=nullfungetInstance(context:Context):ScreenDimen{if(instance==null){synchronized(ScreenDimen::class){if(instance==null){instance=ScreenDimen(context)}}}returninstance!!}}//获得屏幕宽度pixelfungetScreenWidthPix():Int{returndisplayMetrics!!.widthPixels}//获得宽度pixelfungetScreenHeightPix():Int{returndisplayMetrics!!.heightPixels}//获取屏幕宽度dpfunscreenWidthDp():Int{varscreenWidthDp=getScreenWidthPix()/displayMetrics!!.densityreturnscreenWidthDp.toInt()}funscreenHeightDp():Int{varscreenHeightDp=getScreenHeightPix()/displayMetrics!!.densityreturnscreenHeightDp.toInt()}}