全部 文章 问答 分享 共找到143个相关内容
[问答] 喜马拉雅详情页面RecyclerView控件显示不全
喜马拉雅课程中,详情页面DetailActivity的RecyclerView控件最后一项总是显示不全,下了老师的Demo代码运行结果也是这样的,有没有同学遇到这个问题?如果遇到,是怎么解决的呢?
2020-03-16 16:03 · 喜马拉雅
[问答] 博客 跳转到文章详情的时候出错
可是点击某个文章进入详情页面的时候就这样了这是点进详情页面的url就是这个界面报错了没有中文字符啊也没有空格怎么会报错呢这个是页面的跳转代码<a:href="'/article/'+item.id
2020-09-24 16:06 · 博客
[问答] 想问一下各位大佬,这个门户文章详情的图片要居中怎么搞。

想问一下各位大佬,这个门户文章详情的图片要居中怎么搞。

2021-08-01 17:44 · 博客门户
[文章] 喜马拉雅视频教程08-推荐完成了,我们去做一下详情界面
喜马拉雅视频教程08-推荐完成了,我们去做一下详情界面前面我们已经把推荐界面完成了,接下来的话,我们做详情页面吧。
[问答] “27、【领券联盟】编写分类详情的item内容”的代码稍微修改遇到了问题。适配器的使用
“27、【领券联盟】编写分类详情的item内容”的代码稍微修改遇到了问题。
2020-07-28 05:51 · Android / Adapter / 适配器
[问答] 喜马拉雅第19集详情界面一点开就闪退
19989/com.example.eryuI/Process:Sendingsignal.PID:19989SIG:9跟视频对照了好几遍了,代码都是一样的,但是我运行的时候主界面正常,就是不能点击查看详情
2020-05-15 22:28 · 喜马拉雅
[文章] MVVM+Kotlin+组件化 开发的阳光沙滩APP
MVVM+Kotlin+组件化开发的阳光沙滩APP主要功能文章列表,详情摸鱼问答商城个人中心其中有些功能还在开发中...部分截图登录注册文章列表和详情摸鱼列表和详情问答列表和详情商城和个人中心感谢非常感谢
2022-05-18 11:07 · android / 组件化
[问答] Fragment使用出错,详情如下
<fragmentandroid:id="@+id/main_act"android:name="com.huperly.test.HomeFragment"android:layout_width="match_parent"android:layout_height="match_parent"></fragment>也创建了main_act.xml,但Fragment类里inflater.inflate()第一个参数就是不对,网上也没看到类似的问题,也看过好些视频教程,步骤流程没问题,同时还有以下问题,transaction的add和replace都显示过时
2020-03-21 11:06 · Fragment
[问答] 从activity2回到activity1的fragment1,如何保持在activity2中做的更新。
点击其中一个item进入actvity2详情页面,在详情页面也可以进行收藏。在activity2进行收藏后点击返回,如何使得activity1中的fragment的收藏夹也变色。
2020-04-26 11:49 · Android / RecyclerView / Fragment / Activity / 收藏夹
[文章] 滑动 Scrollview 时动态改变 Toolbar 透明度,模仿京东详情页效果
前段时间逛JD时看到详情页滑动时Toolbar改变透明度的效果感觉很不错,想着自己实现一下,于是就有了这篇文章。
2020-09-23 14:05 · android / kotlin / scrollview / toolbar / plaindev
[文章] 国庆前更新的版本,有啥更新的呢?
用户详情点击用户名,可以到用户的详情界面比如说,点击上面的用户名,就转到:添加了标签链接点击标签,可以跳转到标签的集合页面:
2019-09-27 01:09 · 测试 / 公告 / 官方 / 更新 / 版本
[文章] 喜马拉雅项目-订阅数据库设计
有图片、title、描述、播放量、节目数量、作者名称(详情界面)专辑id还记得创建数据库的方法吗?还记得sql语句吗?
2019-08-01 21:39 · sql / 数据库
[文章] 阳光沙滩Android客户端文章优化
首先你需要接入文章详情web页面。
[文章] 【领券联盟】笔记:视频62,63,64-跳转到淘宝
startActivity(taoBaoIntent);}else{ToastUtil.showToast("已经复制,粘贴分享,或打开淘宝");}}});}这时我们手机有淘宝的话,就能跳转到淘宝商品详情
2020-04-04 14:55 · 课堂笔记
[问答] 单activity应用中fragment之间跳转与通信
比如viewpager中的列表fragment点击条目跳转到另外一个详情fragment中应该如何设计
2020-03-25 18:21 · Android
[问答] 喜马拉雅项目,数据库查询到数据后如何让当前的Activity刷新呢?
关于喜马拉雅订阅功能,在点击订阅后,退出程序清空后台在重新进来,点击同样的专辑,显示的是未订阅状态,返回到主页面后再点击该专辑,进来后又是已订阅状态了,打了log如图,可以看到第一次进详情页时查询当前专辑的结果还是
2020-02-24 22:32 · 喜马拉雅项目
[文章] 仿断点沙滩APP用户详情下拉功能
其实应该不是很困难大家都知道是AppBarLayout+CollapsingToolbarLayout+Toolbar进行UI控制的主要想写篇文章记录下效果且排下坑不是最优解是土办法来着有大佬有新写法可以指导下有问题可以sob联系dd1.关于图片(头像)一直无法跟随文字一起显示在toolbar这点进行了多次尝试1)将imgview放置在toolbar中发现无法控制它的位置(无法居中处理)因为toolbar内没有提供位置的一些方法所以无疾而终2)放在了toolbar同级也是感觉没啥用没办法跟随文本一起隐藏(这里是坑)3)放在appbar内与CollapsingToolbarLayout同级会出现拉扯不符合该方案(放弃)在咨询断点大佬后他说他是采用2)可是我自己的没办法跟随隐藏或显示我就不断去查看所写的属性心想来个大破大立将我原先写的CollapsingToolbarLayout内的属性先隐藏掉在动态填入背景就好了巧了删除了2)方案就能和断点大佬的效果一样imgview能跟随文本在toolbar中了大家可以猜猜是啥属性卖关子(其实就一个属性是限制了因为它操作后又被赋值了个背景所以imgview跟随不了toolbarapp:contentScrim="@drawable/userinfo_bg"神坑其实只要解决这个问题其他问题就不是很大了)因为toolbar自身会移动只要解决imgview移动就好了(百分比计算然后移动就好了并不困难(os感谢断点大佬点拨哈哈哈哈)因为没做view大小变化这个留给下个有缘人探索下先贴贴xml代码(自行删减)<?xmlversion="1.0"encoding="utf-8"?><androidx.coordinatorlayout.widget.CoordinatorLayoutandroid:layout_width="match_parent"xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:orientation="vertical"android:layout_height="match_parent"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/app_bar"android:layout_width="match_parent"android:layout_height="wrap_content"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:id="@+id/ctl_test"android:layout_width="match_parent"android:layout_height="wrap_content"app:expandedTitleGravity="center"app:collapsedTitleGravity="left"app:layout_scrollFlags="scroll|exitUntilCollapsed"><!--app:contentScrim="@drawable/userinfo_bg"--><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/rl_top"><ImageViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_220"android:id="@+id/iv_user_bg"android:background="@drawable/userinfo_bg"android:scaleType="centerCrop"/><includelayout="@layout/layout_title"android:id="@+id/ll_user_title"android:visibility="invisible"/><de.hdodenhof.circleimageview.CircleImageViewandroid:padding="@dimen/dp_5"android:layout_width="@dimen/dp_80"android:layout_height="@dimen/dp_80"android:layout_below="@+id/iv_user_bg"android:layout_marginTop="-40dp"android:visibility="gone"android:layout_marginLeft="@dimen/dp_20"/><includeandroid:id="@+id/ic_user_fansorfollow"layout="@layout/layout_info_fof"android:layout_below="@+id/tv_user_position"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"app:layout_collapseMode="parallax"/></RelativeLayout><de.hdodenhof.circleimageview.CircleImageViewandroid:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"android:background="@drawable/emoji_2"android:layout_gravity="center"android:layout_marginTop="-50dp"app:layout_collapseMode="pin"android:layout_marginBottom="@dimen/dp_5"android:id="@+id/iv_user_avatar"/><androidx.appcompat.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="@dimen/dp_80"app:layout_collapseMode="pin"app:titleTextColor="@color/white"android:id="@+id/toolbar"/></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><androidx.viewpager.widget.ViewPagerandroid:id="@+id/vp_user"android:layout_width="match_parent"android:layout_below="@+id/ic_user_fansorfollow"android:layout_marginTop="@dimen/dp_5"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior">//这一句是很重要的提供关联上面的指示器(应该是这么叫吧)<com.google.android.material.tabs.TabLayoutandroid:id="@+id/tab_user"android:layout_width="match_parent"android:layout_height="wrap_content"app:tabGravity="fill"app:tabIndicatorColor="@color/index_blue"app:tabIndicatorFullWidth="false"app:tabIndicatorHeight="1dp"app:tabMode="fixed"app:tabSelectedTextColor="@color/bottom_navigation_item_bg_color"app:tabTextColor="@color/index_black"/></androidx.viewpager.widget.ViewPager><androidx.recyclerview.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/rc_uinfo"android:visibility="gone"<!--可以拿这个先测试-->/></androidx.coordinatorlayout.widget.CoordinatorLayout>java代码只能给一部分相关的内容了因为这不是demo没办法copy运行想实践的可以运行看看privateFragmentUserinfoNewBindingbinding=null;privateUserInfoPresentermPresenter;privateString[]titles=newString[]{"动态","文章"/*,"问答"*/,"关注","粉丝"};privateList<String>mStrings=newArrayList<>();privateList<Fragment>fragments=newArrayList<>();privateStringuserId;privateVpAdaptervpAdapter;@Nullable@OverridepublicViewonCreateView(@NonNullLayoutInflaterinflater,@NullableViewGroupcontainer,@NullableBundlesavedInstanceState){binding=FragmentUserinfoNewBinding.inflate(inflater,container,false);initData();initView();returnbinding.getRoot();}privateintappbarHeight=0;//整块高度privateinttoolbarHeight=0;//缩略后高度privateintivAvatarHeight=0;//头像宽高privatefloativAvatarX;//所在X轴privatevoidinitView(){vpAdapter=newVpAdapter(getChildFragmentManager(),fragments,getContext(),mStrings);appbarHeight=UiUtils.dp2px(getActivity(),220f);toolbarHeight=UiUtils.dp2px(getActivity(),80f);ViewGroup.LayoutParamslayoutParams1=binding.ivUserAvatar.getLayoutParams();ivAvatarHeight=layoutParams1.width;binding.toolbar.setTitleMarginStart(ivAvatarHeight+5);ivAvatarX=UiUtils.getWidth(getContext())/2-ivAvatarHeight/2-5;//所在的X轴//绘制背景Glide.with(getActivity()).load(R.drawable.userinfo_bg).transform(newBlurTransformation(5,1))//高斯模糊第三方库.into(binding.ivUserBg);binding.vpUser.setAdapter(vpAdapter);binding.tabUser.setupWithViewPager(binding.vpUser);//title文章binding.icUserFansorfollow.tvArtNum.setOnClickListener(v->binding.vpUser.setCurrentItem(1));//title关注binding.icUserFansorfollow.tvFollow.setOnClickListener(v->binding.vpUser.setCurrentItem(2));//title粉丝binding.icUserFansorfollow.tvFans.setOnClickListener(v->binding.vpUser.setCurrentItem(3));binding.llUserTitle.ivTtFinish.setOnClickListener(v->getActivity().finish());//设置展开前后的UIbinding.ctlTest.setExpandedTitleColor(ContextCompat.getColor(getContext(),R.color.white));binding.ctlTest.setCollapsedTitleTextColor(ContextCompat.getColor(getContext(),R.color.white));intstatusBarHeight=UIStatusBarUtils.getStatusBarHeight(getActivity());//获取状态栏高度RelativeLayoutrl_title=binding.llUserTitle.getRoot();RelativeLayout.LayoutParamslayoutParams=(RelativeLayout.LayoutParams)rl_title.getLayoutParams();layoutParams.topMargin=statusBarHeight;//设置状态栏高度}privatevoidinitData(){mPresenter=newUserInfoPresenter(this);userId=getActivity().getIntent().getStringExtra(Constance.S_DATA);StringuuserId=getArguments().getString(Constance.S_DATA);/*TODOtestif(!uuserId.equals(SpUtils.getInstance().getString(Constance.SP_UID,""))){binding.btnIsfans.setVisibility(View.GONE);}*/mPresenter.getOtherUserAchievement(uuserId);mPresenter.getUserInfo(uuserId);//添加fragmentfragments.add(newMoyuFragment(uuserId,true));fragments.add(newArticleFragment(uuserId,true));//fragments.add(newQandAFragment());fragments.add(newFansUserFragment(userId,2));//关注fragments.add(newFansUserFragment(uuserId,1));//粉丝//添加标题mStrings.clear();for(inti=0;i<titles.length;i++){mStrings.add(titles[i]);}binding.appBar.addOnOffsetChangedListener(newAppBarLayout.OnOffsetChangedListener(){@OverridepublicvoidonOffsetChanged(AppBarLayoutappBarLayout,intverticalOffset){floatpercentage=Math.abs((float)verticalOffset/(float)(appbarHeight-toolbarHeight));binding.ivUserAvatar.setTranslationX(-ivAvatarX*percentage);//移动位置if(percentage>0.5){//控制其他空间隐藏binding.icUserFansorfollow.llFansorfollow.setVisibility(View.GONE);}else{binding.icUserFansorfollow.llFansorfollow.setVisibility(View.VISIBLE);}}});@OverridepublicvoidonGetUserInfo(UserInfouserInfo){if(userInfo.isSuccess()){UserInfo.DataBeandata=userInfo.getData();UiUtils.isVipImageView(getActivity(),data.isVip(),binding.ivUserAvatar,data.getAvatar());Stringcover=data.getCover();//背景if(!TextUtils.isEmpty(cover)){Glide.with(getActivity()).load(cover).transform(newBlurTransformation(5,1)).into(binding.ivUserBg);}//填入在toolbar是因为可以动态设置外边距binding.toolbar.setTitle(data.getNickname());binding.tvUserPosition.setText(position.toString());}}各位大佬嘴上留情有其他思路也可以评论一起学(指导)习(我)
2022-08-05 11:48 · 下拉效果 / 仿断点APP
[文章] 阳光沙滩Android客户端和web通信
背景之前已经写过一篇关于文章详情和问答详情通信文章,目前由于需求优化,更新文章问答相关的通信协议,所以接入了文章详情和问答的需要同步更新协议。
2022-04-14 22:24 · Android / vue / 原生调用web / web / web调用原生
[问答] 淘口令请求回来不正确
有没有跟我一样淘口令请求回来是这样子的呀然后跳转淘宝的话就直接是商品详情页面不是领券页面了
2021-01-20 16:50 · 领券联盟
[文章] 动画详情之属性动画(二)
1.ValueAnimator1.1引入属性动画的原因视图动画虽然能够实现控件的透明度变化、移动、拉伸、旋转,但是无法改变控件的内部属性。看过上篇文章的知道,本质上视图动画就是通过强制父容器重新绘制子View来实现,但是并没有改变子view的内部属性(如颜色,大小,宽高,位置)。例如将TextView从位置A移动到位置C,分别使用视图动画和属性动画。-视图动画中,如果给子view设置点击事件,只有在子view的初始位置(A)才会触发点击事件,点击子view的最终位置(C)或者移动轨迹中的位置(B)都不会触发点击事件。属性动画主要针对控件的某个属性做动画。-属性动画中,动画开始前,点击位置A触发点击事件,动画开始时,点击运动中的控件即位置B可触发点击事件,动画结束时,点击位置C触发点击事件1.2ValueAnimator的简单使用第一步,创建ValueAnimator实例valanimator=ValueAnimator.ofInt(0,400).apply{duration=2000}animator.start()在这里我们利用ValueAnimator.ofInt()创建了一个值从0到400变化的动画,动画时长为2s,从代码中,可以看到,valueAnimator没有和任何控件相关联,只是进行了值的计算,-下一步我们需要对valueAnimator的值进行监听,然后自己根据valueAnimator的值来控制控件animator.addUpdateListener{valcurValue=it.animatedValue.toString()Log.d("qin",curValue)//根据valueAnimmator的值来变换textview的位置tvText.layout(500,curValue.toIntOrNull()?:0,500+tvText.width,(curValue.toIntOrNull()?:0).plus(tvText.height))}打印log如下注意看打印出来的值不一定连续,有可能重复,有知道原因的好兄弟可以在评论区说一下1.3常用函数publicstaticValueAnimatorofInt(int...values)接收可变长参数,接收的参数越多,变化越多越复杂publicstaticValueAnimatorofFloat(Float...values)接收可变长参数,接收的参数越多,变化越多越复杂ValueAnimatorsetDuration(longduration)设置动画持续时间ObjectgetAnimatedValue()监听ValueAnimator动画,获取当前的值start()开始动画setRepeatCount(intvlaue)设置循环次数,值为INFININTE(无限循环动画时,在Activity结束时,需要手动调用cancel(),防止内存泄露setRepeatMode(intvalue)设置循环模式,值为ValueAnimator.REVERSE或者ValueAnimator.RESTARTvoidcancel()取消动画removeUpdateListener(AnimatorUpdateListenerlistener)移除值变化监听器removeAllUptateListeners()移除所有值变化的监听器removeListener(AnimatorListenerlistener)移除Animator中指定的监听器removeAllListeners()移除所有监听器publicvoidsetStartDelay(longstartDelay)设置动画延迟多少秒开始例子如下valanimator=ValueAnimator.ofFloat(0f,100f,30f,300f)animator.duration=3000animator.addUpdateListener{valcurValueFloat=it.animatedValue.toString()valcurValue=curValueFloat.toIntOrNull()tv.layout(curValue?:0,curValue?:0,(curValue?:0).plus(tv.width),(curValue?:0).plus(tv.heigth))}上面代码实现了将textview将从屏幕(0,0)移动到(100,100),再移动到(30,30),最后移动到(300,300)ValueAnimator有两个不同的监听器,一个addUpdateListener监听值的变化过程,一个AnimatorListener监听动画的某个瞬间publicstaticinterfaceAnimatorListener{voidonAnimatorStart(Animatoranimation);//动画开始voidonAnimatorEnd(Animatoranimation);//动画结束voidonAnimatorCancel(Animatoranimation);//动画取消voidonAnimatorRepeat(Animatoranimation);//动画重复}开发者可以通过监听ValueAnimator的四个状态start、end、cancel、repeat,来针对动画的不同状态做出特殊处理。1.4插值器(Interpolator)在线画图工具1.4.1AcclerateDecelerateInterpolator(加速减速插值器)找到它的源码,找出计算方式@HasNativeInterpolatorpublicclassAccelerateDecelerateInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{//...省略其他代码publicfloatgetInterpolation(floatinput){return(float)(Math.cos((input+1)*Math.PI)/2.0f)+0.5f;}}可以看出,这时一个余弦函数,使用了这个插值器,刚开始动画的变化速率较慢,然后慢慢加快,最后减慢,然后不断循环,斜率越大的地方,变化越快。1.4.2AnticipateInterpolatorAnticipateInterpolator是初始偏移插值器,表示动画刚开始时向前偏移一段距离,然后应用动画跟踪源码publicclassAnticipateInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{privatefinalfloatmTension;publicAnticipateInterpolator(){mTension=2.0f;}//省略其他代码publicfloatgetInterpolation(floatt){//a(t)=t*t*((tension+1)*t-tension)returnt*t*((mTension+1)*t-mTension);}使用画图工具得出下面图:因为x从0开始,刚开始时,向y轴的反方向移动,然后在继续向正方向移动,1.4.3BounceInterpolator弹跳插值器,模拟了控件自由落地后回弹的效果@HasNativeInterpolatorpublicclassBounceInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{publicBounceInterpolator(){}@SuppressWarnings({"UnusedDeclaration"})publicBounceInterpolator(Contextcontext,AttributeSetattrs){}privatestaticfloatbounce(floatt){returnt*t*8.0f;}publicfloatgetInterpolation(floatt){//_b(t)=t*t*8//bs(t)=_b(t)fort<0.3535//bs(t)=_b(t-0.54719)+0.7fort<0.7408//bs(t)=_b(t-0.8526)+0.9fort<0.9644//bs(t)=_b(t-1.0435)+0.95fort<=1.0//b(t)=bs(t*1.1226)t*=1.1226f;if(t<0.3535f)returnbounce(t);elseif(t<0.7408f)returnbounce(t-0.54719f)+0.7f;elseif(t<0.9644f)returnbounce(t-0.8526f)+0.9f;elsereturnbounce(t-1.0435f)+0.95f;}效果图如下![图片描述]下落时,首先超过了动画的极限1,然后进行第一次回弹,先上移动,速度由快到慢到快,进行第二次回弹,先快到慢,减速1.4.4OvershootInterpolator结束偏移插值器,表示在动画结束时,沿着动画方向继续运动一段距离后结束动画,查看源码publicclassOvershootInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{privatefinalfloatmTension;publicOvershootInterpolator(){mTension=2.0f;}//..省略代码mTension=a.getFloat(R.styleable.OvershootInterpolator_tension,2.0f);setChangingConfiguration(a.getChangingConfigurations());a.recycle();}publicfloatgetInterpolation(floatt){//_o(t)=t*t*((tension+1)*t+tension)//o(t)=_o(t-1)+1t-=1.0f;returnt*t*((mTension+1)*t+mTension)+1.0f;}}画出对应的数学图像在动画快要结束的时候,随着时间的推移,动画进度会超过结束的位置,然后再逐渐返回。1.4.5AnticipateOvershootInterpolatorAnticipateOvershootInterpolator是AniticipateInterpolator和OvershootInterpolator的结合体,即在动画开始时,先向前偏移一段,动画结束时向后偏移一段。跟踪代码@HasNativeInterpolatorpublicclassAnticipateOvershootInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{privatefinalfloatmTension;publicAnticipateOvershootInterpolator(){mTension=2.0f*1.5f;}//省略其他代码privatestaticfloata(floatt,floats){returnt*t*((s+1)*t-s);}privatestaticfloato(floatt,floats){returnt*t*((s+1)*t+s);}publicfloatgetInterpolation(floatt){//a(t,s)=t*t*((s+1)*t-s)//o(t,s)=t*t*((s+1)*t+s)//f(t)=0.5*a(t*2,tension*extraTension),whent<0.5//f(t)=0.5*(o(t*2-2,tension*extraTension)+2),whent<=1.0if(t<0.5f)return0.5f*a(t*2.0f,mTension);elsereturn0.5f*(o(t*2.0f-2.0f,mTension)+2.0f);}}1.4.6LinearInterpolator这个是我们最常见的插值器,表示匀速@HasNativeInterpolatorpublicclassLinearInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{//...省略其他代码publicfloatgetInterpolation(floatinput){returninput;}}1.4.7AccelerateInterpolator加速插值器,表示动画开始速率改变的比较慢,然后开始加速计算方式为:publicclassAccelerateInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{privatefinalfloatmFactor;privatefinaldoublemDoubleFactor;publicAccelerateInterpolator(){mFactor=1.0f;mDoubleFactor=2.0;}//省略其他代码publicfloatgetInterpolation(floatinput){if(mFactor==1.0f){returninput*input;}else{return(float)Math.pow(input,mDoubleFactor);}}}1.4.8DecelerateInterpolator减速插值器,在动画开始时一瞬间加速到最大值,然后逐渐变慢publicclassDecelerateInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{publicDecelerateInterpolator(){}//省略其他代码publicfloatgetInterpolation(floatinput){floatresult;if(mFactor==1.0f){result=(float)(1.0f-(1.0f-input)*(1.0f-input));}else{result=(float)(1.0f-Math.pow((1.0f-input),2*mFactor));}returnresult;}##1.6ValueObject进阶OfObject()1.4.9循环插值器CycleInterpolator是循环插值器,表示动画循环播放特定的次数,速率沿着正弦曲线变化,publicclassCycleInterpolatorextendsBaseInterpolatorimplementsNativeInterpolator{publicfloatgetInterpolation(floatinput){return(float)(Math.sin(2*mCycles*Math.PI*input));}privatefloatmCycles;}画出循环2次的函数图像红色方框代表一次循环2ObjectAnimator2.1基本使用上面我们通过ValueAnimator对动画的值进行变化,如果想要改变某个控件的属性,还要监听valueAnimator的动画过程,使用起来比较复杂。ObjectAnimator就是为了解决这个问题,相对于ValueAnimator,ObjectAnimator简化使用的API。ObjectAnimator是ValueAnimator的子类,所有ValueAnimator的方法都可以使用,同时对ofInt()、ofFloat()方法进行了重写,使用方法为:valanimator=ObjectAnimator(tv,"float",1f,0f,1.0f)animator.duration=1000animator.start()上面代码实现了TextView的透明度从1变到0再变到1,从上面的代码中可以看到,构造ObjectAnimator的方法非常简单publicstaticObjectAnimatorofFloat(objecttarget,stringpropertyName,float...values)第一个参数用于指定动画要操作的控件第二个参数指定动画要操作的属性第三个参数,可变长参数,上面的代码透明度从1到0再到12.2ObjectAnimaor原理ObjectAnimator通过构造方法ObjectAnimator()的第2个参数,propertyName,来调用相应的Set()方法,他们定义在View中//设置透明度publicvoidsetAlpha(floatalpha)//设置绕Z旋转publicvoidsetRotation(floatrotation)//设置绕x轴旋转publicvoidsetRotationX(floatrotationX)//设置绕y轴旋转publicvoidsetRotationY(floatrotationY)//设置移动publicvoidsetTranslateX(floattranslateX)publicvoidsetTranslateY(floattranslateY)//设置缩放publicvoidsetScaleX(floatscaleX)publicvoidsetScaleY(floatscaleY)2.3自定义控件中如何使用ObjectAnimator首先我们要知道使用ObjectAnimator的前提是,view中有属性名字对应的set(),然后就是set()方法的命名方法是小驼峰,即set后对应的每个单词首字母大写,其余小写3AnimatorSetAnimatorSet可以将ValueAnimator和ObjectAnimator组合到一起,实现组合动画,3.1playSequentially()函数说明如下publicvoidplaySequentially(Animator...items)publicvoidplaySequentially(List<Animator>items)playSequentially()的意思是先执行完动画一,再执行动画二,动画三3.2playTogether函数说明如下publicvoidplayTogether(Animator...items)publicvoidplayTogether(List<Animator>items)AnimatorSet中没有设置循环次数的函数,是否无限循环主要看动画本身,和playTogether()、playSequntially()无关3.3AnimatorSet.Builder虽然使用playTogether()和playSquentially()分别能实现动画依次播放和同时开始动画,但是不能非常自由第组合动画,比如我们有3个动画A、B、C,想先播放C,利用上面两个函数没办法实现。valanimatorSet=AnimatorSet()valbuidler=animator.play(tv1)builder.with(tv1TranslateY)AnimatorSet.play()这个方法生成Builder()的唯一方法,//表示要播放某个动画publicBuilderplay(Animatoranim)//和前面动画一起执行publicBuilderwith(Animatoranim)//先执行此动画,在执行前面的动画publicBuilderbefore(Animatoranim)//在前面的动画执行完之后,再执行此动画publicBuilderafter(Animatoranim)//延迟n毫秒之后执行动画publicBuilderafter(longdelay)添加监听器,AnimatorSet和ValueAnimator都是同一个父类Animator,所以可以添加下面的监听器publicstaticinterfaceAnimatorListener{voidonAnimatorStart(Animatoranimation);//动画开始voidonAnimatorEnd(Animatoranimation);//动画结束voidonAnimatorCancel(Animatoranimation);//动画取消voidonAnimatorRepeat(Animatoranimation);//动画重复}4.Evaluator(估值器、计算器)我们知道创建ValueAnimator实例方法是调用valueAnimator的ofInt(),ofFloat()或者ofObject()静态方法ofInt()和ofFloat()的计算前面我们都学会了,那么ofObject()呢?初始对象和结束对象,如何过渡?或者说这玩意怎么用?Android原生提供了以下几种Evaluator-IntEvaluator:用于计算int类型属性值的估值器-FloatEvaluator:用于计算Float类型属性值的估值器-ArgbEvaluator:用于计算十六进制形式表示颜色值的估值器-TypeEvaluator:估值器的接口,我们可以实现这个接口来完成自定义估值器下面我们先来看IntEvaluator内部是怎么是怎么实现的4.1IntEvaluator内部实现publicclassIntEvaluatorimplementsTypeEvaluator<Integer>{publicIntegerevaluate(floatfrcation,IntegerstartValue,IntegerendValue){intstartInt=startValue;return(int)(start+fraction*(endValue-startInt);}}fraction参数,插值器(Interpolator)中的返回值,以百分制的小数形式表示startValue和endValue分别对应ofInt(intstart,intend)函数中的start和end的数值,比如我们的动画ofInt(100,300)进行到数值进度为20%,那么fraction=0.2startvalue=100,endValue=300返回值就是当前数值监听器所得到的具体数值,可以通过addUpdateListener监听器进行监听器,然后调用animation.getAnimatedValue()函数得到解决。计算公式:返回值=startValue+(endValue-startValue)*fraction动画的值=初始值+完成度*(结束值-初始值)如果我们想告诉系统如何从初始对象过度到结束对象,那么我们就要自己来实现TypeEvaluator接口,即自定义Evaluator整个流程为:+ofInt(0,400):定义动画数值区间+插值器:返回当前动画的进度,比如说30%+Evaluator:根据插值器返回的动画进度,计算出动画的值,公式为动画的值=初始值+完成度*(结束值-初始值)+然后开发者在监听器addUpdateListener中监听,获取到动画的值4.2插值器和Evaluator的区别插值器只能改变动画速度的快慢,而Evaluator可以通过接收插值器中的动画进度,增加一些自己对动画的处理,改变在addUpdateListener中的值,通过Evaluator与ofObject的配合,使得valueAnimator更加强大,在Evaluator的处理中,可以给监听器返回一个自定义的对象。5.PropertyvlauesHolder和KeyframeValueAnimator和ObjectAnimator除了提供ofInt(),ofFloat(),ofObject()方法外,还提供了一个ofPropertyValuesHolder()publicstaticValueAnimatorofPropertyValuesHolder(PropertyVlauesHolder...vlaues)publicstaticObjbectAnimatorofPropertyValuesHolder(PropertyValuesHolder...values)ValueAnimator和ObjectAnimator的ofPropertyValuesHolder差不多,这里以ObjectAnimator为例子5.1概述PropertyValuesHolder类的含义就是,它其中保存了动画过程所需要操作的属性和对应的值,我们同构ofFloat(Objecttarget,StringpropertyName,float...values)构建的动画,ofFloat()内部实现其实就是将传入的参数封装成PropertyValuesHolder实例来保存动画状态,后面的各种操作也是以PropertyValusHolder为主。下面是源码publicfinalclassObjectAnimatorextendsValueAnimator{publicstaticObjectAnimatorofFloat(Objecttarget,StringpropertyName,float...values){ObjectAnimatoranim=newObjectAnimator(target,propertyName);anim.setFloatValues(values);returnanim;}}点击setFloatValue()//ObjectAnimator.java中@OverridepublicvoidsetFloatValues(float...values){if(mValues==null||mValues.length==0){//Novaluesyet-thisanimatorisbeingconstructedpiecemeal.Initthevalueswith//whateverthecurrentpropertyNameisif(mProperty!=null){setValues(PropertyValuesHolder.ofFloat(mProperty,values));}else{setValues(PropertyValuesHolder.ofFloat(mPropertyName,values));}}else{super.setFloatValues(values);}}//ValueAnimator.java中publicvoidsetValues(PropertyValuesHolder...values){intnumValues=values.length;mValues=values;mValuesMap=newHashMap<String,PropertyValuesHolder>(numValues);for(inti=0;i<numValues;++i){//封装成了PropertyValuesHolder实例PropertyValuesHoldervaluesHolder=values[i];mValuesMap.put(valuesHolder.getPropertyName(),valuesHolder);}//Newproperty/values/targetshouldcausere-initializationpriortostartingmInitialized=false;}跟踪到这里我们验证了刚刚结论,动画的状态和参数被封装成了封装成了PropertyValuesHolder实例,并存在以属性名为键的HashMap中5.2PropertyValusHolder的常用函数publicstaticPropertyValuesHolderofFloat(StringpropertyName,float...values)publicstaticPropertyVlauesHolderofInt(StringpropertyName,int...values)publicstaticPropertyValuesHolderofObject(StringpropertyName,TypeEvaluatorevaluator,object...values)publicstaticPropertyValuesHolderofKeyframe(StringpropertyName,keyframe..values)propertyName表示ObjectAnimator需要操作的属性名,ObjectAnimator通过反射操作对应的setProperty()values属性所对应的参数,同样是可变长参数,可以指定多个,如果只指定了一个,那么ObjectAnimator会通过查找对应属性getProperty()来获取初始值,5.3设置PropertyValuesHolder实例ObjectAnimator给我们提供了一个设置PropertyValuesHolder实例的入口publicstaticObjecetAnimatorofPropertyValuesHolder(Objecttarget,PropertyValuesHolder...values)target需要执行动画的控件values可变长参数,可以传入多个PropertyValuesHolder实例,由于每个PropertyValuesHolder实例都会针对一个属性执行动画,所以PropertyValuesHolder实例,则会对控件的多个属性同时执行动画操作。示例如下:5.4Keyframe前面提到,要想动画速率的变化,可以通过自定义插值器,也可以通过自定义Evaluator来实现,但是如果真的让我们从速率变化效果而自定义插值器或者Evaluator大部分要涉及数学知识,恐怕也不容易。谷歌为根据电影的原理,为我们提供了KeyFrame这一套API,只需要知道动画某个进度点的关键帧,然后API会根据各个帧之间的先后顺序进行平滑过渡。5.4.1生成关键帧publicstaticKeyframeofFloat(floatfraction,floatvalue)fraction当前动画的进度,即插值器中getInterpolation()的返回值value:当前动画当前所在的数值的位置比如Keyframe.ofFloat(0,0)表示动画进度为0时,动画所在数值的位置为0,Keyframe.ofFloat(0.25f,-20f)表示动画进度为25时,动画所在的数值为-20,5.4.2关键帧的使用valframe0=Keyframe.ofFloat(0f,0)valframe1=Keyframe.ofFloat(0.1f,-20f)valframe2=keyframe.ofFloat(1f,0)valframeHolder=PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2)valanimator=ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder)animator.duration=1000animator.start()Keyframe也有一些常用的其他函数用来设置fraction、value、和Interpolator//设置KeyFrame所对应的进度publicvoidsetFraction(floatfraction)//设置KeyFrame所对应的值publicvoidsetValue(Objectvalue)//设置插值器//表示从上一帧到这一帧使用这个插值器publicvoidsetInterpolator(TimeInterpolatorinterpolator)实际中使用可以这样valkeyframe3=Keyframe.ofFloat(1)keyframe2.value=0f//对于keyframe而言,fraction和value这两个参数必须有的,所以不论使用哪种方法实例化Keyframe,都必须保证这两个值被初始化。//没有使用插值器,系统默认调用线性插值器5.5PropertyValuesHolder的其他函数PropertyValuesHolder除了拥有上面讲到的ofInt(),ofFloat(),ofObject(),ofKeyframe()还有其他函数//设置动画的EvaluatorpublicvoidsetEvaluator(TypeEvaluatorevaluator)//设置ofFloat()所对应的动画值列表publicvoidsetFloatValues(float...values)//用于设置ofInt()所对应的动画值列表publicvoidsetIntValues(int...values)//用于设置ofkeyframe()所对应的动画值列表publicvoidsetKeyframes(Keyframe...values)//用于设置ofObject()所对应的动画值列表publicvoidsetObjectValues(Object...values)//设置动画属性名publicvoidsetPropertyName(StringpropertyName)6为ViewGroup内组件添加动画前面讲述的ViewAnimator、ObjectAnimator、AnimatorSet都只能针对一个控件做动画,如果我们想对ViewGroup内部控件做统一的入场动画、处场动画,如Recyclerview里面的item的添加、删除、数据更新时的动画,上面3个动都无法做到。为了解决这个问题,androidAPI11开始提供了一个简单的属性android:animateLayoutChanges="true/false",所有的ViewGroup类控件都有这个属性,只要在xml添加了这个属性,就能实现在添加、删除viewGroup内部控件时的默认动画,但是这个动画不能自定义6.1LayoutTransition上面我们体验了android给我们提供的viewGroup在增加、删除子控件时的默认动画,但是无法使用自定义动画。为了使用自定义动画,我们可以使用LayoutTransition-创建LayoutTransition示例创建动画并进行设置将LayoutTransition设置到ViewGroup中valtransitioner=LayoutTransition()valanimOut=ObjectAnimator.ofFloat(null,"rotation",0f,90f,0f)transitioner.setAnimator(LayoutTransition.DISAPPEARING,animOut)linearLayout.layoutTransition=transitioner在第二步中,transitioner.setAnimator设置动画的函数声明如下publicvoidsetAnimator(inttransitionType,Animatoranimator)其中transitionType表示应用当前动画的对象范围,取值如下:-APPERAING:元素在容器中出现是所定义的动画-DISAPPEARING:元素在容器中消失时所定义的动画-CHANGE_APPEARING:由于容器中要显示一个新的元素,其他需要变化的元素所应用的动画-CHANGE_DISAPPEARING:由于容器中某个元素消失时,其他需要便是的元素所应用的动画LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须要使用PropertyValuesHolder所构建的动画才会有效果,也就是说使用ObjectAnimator构建的动画,在这里不会有效果。6.2其他函数//设置所有动画完成所需要的时间publicvoidsetDuration(longduration)//针对某个Type设置动画时长publicvoidsetDuration(inttransitionType,longduration)//设置单个Type的插值器publicvoidsetInterpolator(inttransitonType,TimeInterpoloatorinterpolator)//针对单个type设置动画延时publicvoidsetStartDelay(inttransitionType,longdelay)//针对单个Type设置每个子item动画的时间间隔//参数一:transitionType用于指定Type类型的动画//参数二:各个item间做动画的间隔publicvoidsetStagger(inttransitionType,longduration)6.3设置监听LayoutTransition提供了一个监听函数publicvoidaddTransitionListener(TransitionListenerlistener)//其中TransitionListenerpublicinterfaceTransitionListener{publicvoidstartTransition(LayoutTransitiontransition,ViewGroupviewGroup,Viewview,inttransitionType)publicvoidendTransition(LayoutTransitiontransition,ViewGroupviewGroup,Viewview,inttransitionType)}在任何类型的LayoutTransition开始和结束时,都会调用TransitionListener的startTransition()和endTransition(),在transitionListener有4个参数LayoutTransitiontransiton当前的LayoutTransition实例ViewGroupcontainer当前应用LayoutTransition的容器Viewview当前正在做动画的View对象inttransitionType:当前的LayoutTransition类型取值有:APPEARING,DISAPPEARING,CHANGE_APPEARING和CHANGE_DISAPPEARING下一篇预告:动画实战实例
2022-08-21 17:08 · android / 动画
[文章] WebStorm提示TypeError: this.cliEngine is not a constructor
WebStorm提示TypeError:this.cliEngineisnotaconstructor点击detail详情内容上图中会告诉你哪个插件出问题了:npminstall--save-deveslint
2020-07-06 12:03 · Eslint / Js / 前端开发 / 报错 / webstorm
[问答] 喜马拉雅推荐页面内容重复且recyclerVIew出现复用
如何解决推荐页面有多条相同数据,并且点击item进如详情界面跟item里面的内容不一致,recyclerView出现复用BUG
2021-04-13 17:51 · 喜马拉雅
[问答] 领券联盟24节,无数据返回

请问,在领券联盟24节中,请求分类详情内容,无数据返回,在onFailure中返回这个错误,该怎么定位?

2023-01-25 18:39 · 领券联盟
[问答] 服务器如何使用nginx部署多个vue2项目
背景:我新建了一个vue2的项目,通过康师傅的博客api,获取了文章详情的数据进行渲染,本地已经初步调试完成,现在需要部署到服务器中。
2021-08-04 11:44 · vue / nginx / 博客系统
2020-04-02 17:32 · Android
[问答] 喜马拉雅课程第78集,上拉加载结果提示问题
今天在做详情列表上拉加载结果提示的功能时,发现Toast在第一个节目的详情页面正常,没问题。但是点第二个节目进去,加载结束后,加载结果的Toast会提示两次。
2020-09-25 12:49 · Android / 喜马拉雅
[问答] 我在学习《Android开发基础课程》遇到了问题
/1443881236287311874

学习内容:3、下载后台程序以及启动后台程序


时间:0:00


以下是问题详情

2022-08-10 10:49 · 网络编程
[文章] 喜马拉雅项目-订阅数据库设计
有图片、title、描述、播放量、节目数量、作者名称(详情界面)专辑id还记得创建数据库的方法吗?还记得sql语句吗?
[问答] 我在学习《前后端分离项目《博客系统》前端-门户》遇到了问题
1444540338629890049

学习内容:7、阳光沙滩博客系统门户-引入图标样式


时间:138.901864


以下是问题详情

2022-03-24 21:06 · 博客系统
[问答] nuxt动态路由点击跳转是可用的,但是刷新页面之后出现400错误
https://images.sunofbeaches.com/content/2021_12_02/915909379373400064.png">

正常点击,可以跳转到详情页面

2021-12-02 10:24 · nuxt / 博客系统
  • 1
  • 2
  • 3
  • 4
  • 5