模拟视频播放器控制界面时动画效果出现的问题

来源:互联网 发布:c语言做图形界面 编辑:程序博客网 时间:2024/06/10 14:01

需求:

项目要实现一个类似视频播放器控制界面的效果,不过比他简单些,显示有三个部分组成:最上面进行时间和下面的两个控制按钮,点击后屏幕显示,过几秒自动消失。

首先想到的就是前几天刚看的MediaController,所以就把MediaController拿过来简单的看了下,想貌似没有它复杂,赶进度要紧,自己简单实现就好,最后效果如下:



实现思路:

自定义一个view,上面是一个显示时间的文本,设下透明度;下面用一个FrameLayout,先放纵向放两个线性布局在最底层实现下面白条效果,然后把两个文本按钮加在上层;最后在稍微加点进入和退出的动画效果(这个地方出了点粗心的问题,下面提到)。


实现:

首先是自定义view:

public class VideoControlPanel extends FrameLayout implements IVideoControlPanel, AnimationListener, OnTouchListener,Runnable {private static final int DELAYMILLIS = 3 * 1000;private static final int DURATION = 300;private boolean isShowing = false;private Animation topEnter, topExit, buttomEnter, buttomExit;private View mRoot;private TextView tvTitle;private LinearLayout llTitle, llChange, llHangup;private FrameLayout flOperate;private Handler handler = new Handler();public VideoControlPanel(Context context) {super(context);initControllerPanel();}public VideoControlPanel(Context context, AttributeSet attrs) {super(context, attrs);initControllerPanel();}private void initControllerPanel() {initOther();initView();}private void initView() {LayoutInflater inflate = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);mRoot = inflate.inflate(R.layout.media_controller, null);llTitle = (LinearLayout) mRoot.findViewById(R.id.llTitle);flOperate = (FrameLayout) mRoot.findViewById(R.id.flOperate);tvTitle = (TextView) mRoot.findViewById(R.id.tvTitle);llHangup = (LinearLayout) mRoot.findViewById(R.id.llHangup);llChange = (LinearLayout) mRoot.findViewById(R.id.llChange);setOnTouchListener(this);addView(mRoot);show();}private void initOther() {topEnter = new TranslateAnimation(0, 0, -100, 0);topEnter.setDuration(DURATION);topExit = new TranslateAnimation(0, 0, 0, -100);topExit.setDuration(DURATION);topExit.setAnimationListener(this);buttomEnter = new TranslateAnimation(0, 0, 300, 0);buttomEnter.setDuration(DURATION);buttomExit = new TranslateAnimation(0, 0, 0, 100);buttomExit.setDuration(DURATION);}@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {if (mRoot != null) {mRoot.setVisibility(View.GONE);}}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void hide() {isShowing = false;llTitle.startAnimation(topExit);flOperate.startAnimation(buttomExit);}@Overridepublic void show() {if (!isShowing) {mRoot.setVisibility(View.VISIBLE);isShowing = true;llTitle.startAnimation(topEnter);flOperate.setAnimation(buttomEnter);}handler.removeCallbacks(this);handler.postDelayed(this, DELAYMILLIS);}@Overridepublic void run() {hide();}@Overridepublic void setTitle(String title) {if (tvTitle != null) {tvTitle.setText(title);}}@Overridepublic View getHangupView() {return llHangup;}@Overridepublic View getChangeView() {return llChange;}@Overridepublic void setOnClickListener(OnClickListener listener) {// super.setOnClickListener(l);if (llHangup != null) {llHangup.setOnClickListener(listener);}if (llChange != null) {llChange.setOnClickListener(listener);}}@Overridepublic boolean onTouch(View v, MotionEvent event) {show();return false;}}interface IVideoControlPanel {/** * 隐藏操作面板 */public void hide();/** * 显示操作面板 */public void show();/** * 设置标题 *  * @param title */public void setTitle(String title);/** * 获取挂断的View *  * @return */public View getHangupView();/** * 获取切换的View *  * @return */public View getChangeView();}
代码比较简单,所以也就没写注释。先加载xml中定义的布局,然后处理touch事件,最后用一个handle处理界面的消失。下面是布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:id="@+id/llTitle"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:background="#88FFFFFF"        android:gravity="center"        android:orientation="horizontal"        android:padding="8dip" >        <TextView            android:id="@+id/tvTitle"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:gravity="center_horizontal"            android:text="通话时间:15分27秒"            android:textSize="14sp" />    </LinearLayout>    <FrameLayout        android:id="@+id/flOperate"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:orientation="horizontal" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical" >            <ImageView                android:layout_width="match_parent"                android:layout_height="40dp"                android:src="#00FFFFFF" />            <ImageView                android:layout_width="match_parent"                android:layout_height="40dp"                android:src="#88FFFFFF" />        </LinearLayout>        <RelativeLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="12dp" >            <LinearLayout                android:id="@+id/llHangup"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_alignParentLeft="true"                android:layout_marginLeft="42dp"                android:orientation="vertical" >                <TextView                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:drawablePadding="4dp"                    android:drawableTop="@drawable/ic_hangup"                    android:gravity="center"                    android:text="挂断" />            </LinearLayout>            <LinearLayout                android:id="@+id/llChange"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_alignParentRight="true"                android:layout_marginRight="42dp"                android:orientation="vertical" >                <TextView                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:drawablePadding="4dp"                    android:drawableTop="@drawable/ic_change"                    android:gravity="center"                    android:text="切换" />            </LinearLayout>        </RelativeLayout>    </FrameLayout></RelativeLayout>
这个布局的实现思路如上所述。然后就可以使用了,在需要的地方做如下引用:
<com.ttdevs.customcontrolpanel.VideoControlPanel        android:id="@+id/vcpPanel"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_alignParentTop="true"        android:background="@drawable/bg" />
这样就完成了所需效果。

遇到的问题:

在弄动画的时候,出了点问题,折腾了好久,现象为:底部的按钮出现的动画只有程序第一次启动的时候有效,之后就再没效果了。由于对动画不熟悉,也不知道怪什么,开始是像上面那么写的,最后实在没办法做如下修改,即每次都创建buttomEnter,竟然解决问题了:

@Overridepublic void show() {if (!isShowing) {mRoot.setVisibility(View.VISIBLE);isShowing = true;llTitle.startAnimation(topEnter);buttomEnter = new TranslateAnimation(0, 0, 300, 0);buttomEnter.setDuration(DURATION);flOperate.setAnimation(buttomEnter);}handler.removeCallbacks(this);handler.postDelayed(this, DELAYMILLIS);}

虽然效果实现了,但是一直纠结这个动画问题出在哪里。今天整理的时候无意中发现竟然是自己调用有问题导致的:

flOperate.setAnimation(buttomEnter);应该改成:flOperate.startAnimation(buttomEnter);

这样问题就解决了。


最新修改:2013-12-09

上面的问题虽然坚决了,却不知道问题出在哪,为什么解决,今天无意中看到一篇文章(来自:wangjinyu501),又拿过来研究了下,

public void setAnimation (Animation animation)

Added in API level 1

Sets the next animation to play for this view. If you want the animation to play immediately, use startAnimation(android.view.animation.Animation) instead. This method provides allows fine-grained control over the start time and invalidation, but you must make sure that 1) the animation has a start time set, and 2) the view's parent (which controls animations on its children) will be invalidated when the animation is supposed to start.

Parameters
animationThe next animation, or null.
其中提到,想立即启动动画可以使用startAnimation(Animation)。setAnimation允许细粒度的控制(动画的)启动时间和失效,但是这样必须满足两个条件1)设置了动画启动时间,2)执行动画的组件的父视图在动画启动之前需要刷新界面(从wangjinyu501引用来的)。分析下,第一次动画出问题应该是没有设置动画的启动时间,因此在setAnimation()之前加上:

buttomEnter.setStartTime(Animation.START_ON_FIRST_FRAME);
这样即可。那为什么每次都创建就可以播放动画呢,有兴趣可以看看setStartTime的源码或者打印下buttomEnter.hasStarted()的值。


去掉了布局文件后代码:

public class VideoControlPanel extends FrameLayout implements IVideoControlPanel, AnimationListener, OnTouchListener,Runnable {private static final int DELAYMILLIS = 3 * 1000; // 显示延时private static final int DURATION = 300; // 动画持续private boolean isShowing = false;private Animation topEnter, topExit, buttomEnter, buttomExit;private View mRoot;private TextView tvTitle;private RelativeLayout rlParent, rlOperate;private LinearLayout llTitle, llChange, llHangup, llOperateBg;private FrameLayout flOperate;private Handler handler = new Handler();public VideoControlPanel(Context context) {super(context);initControllerPanel();}public VideoControlPanel(Context context, AttributeSet attrs) {super(context, attrs);initControllerPanel();}private void initControllerPanel() {initOther();initView();}private void initView() {mRoot = initCustomView();setOnTouchListener(this);addView(mRoot);show();}private View initCustomView() {rlParent = new RelativeLayout(getContext());rlParent.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));// 上部分llTitle = new LinearLayout(getContext());llTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 60));llTitle.setOrientation(LinearLayout.VERTICAL);llTitle.setBackgroundColor(Color.parseColor("#90FFFFFF")); // TODOllTitle.setGravity(Gravity.CENTER);tvTitle = new TextView(getContext());tvTitle.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));tvTitle.setGravity(Gravity.CENTER);tvTitle.setTextSize(18);llTitle.addView(tvTitle);RelativeLayout.LayoutParams rlpTop = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.WRAP_CONTENT);rlpTop.addRule(RelativeLayout.ALIGN_PARENT_TOP);rlParent.addView(llTitle, rlpTop);// 下部分flOperate = new FrameLayout(getContext());flOperate.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.WRAP_CONTENT));// 下部分背景llOperateBg = new LinearLayout(getContext());llOperateBg.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));llOperateBg.setOrientation(LinearLayout.VERTICAL);addBackgroundView("#00FFFFFF");addBackgroundView("#90FFFFFF");flOperate.addView(llOperateBg);// 下部分按钮rlOperate = new RelativeLayout(getContext());rlOperate.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));// 下部分按钮挂断llHangup = getButtomLayout("挂断", R.drawable.ic_hangup);addBottomView(true, llHangup);// 下部分按钮切换llChange = getButtomLayout("切换", R.drawable.ic_change);addBottomView(false, llChange);flOperate.addView(rlOperate);RelativeLayout.LayoutParams rlpBottom = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);rlpBottom.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);rlParent.addView(flOperate, rlpBottom);return rlParent;}private void addBackgroundView(String color) {ImageView ivBg = new ImageView(getContext());ivBg.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 80));ivBg.setBackgroundColor(Color.parseColor(color));llOperateBg.addView(ivBg);}private LinearLayout getButtomLayout(String text, int drawId) {LinearLayout llChange = new LinearLayout(getContext());llChange.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));llChange.setOrientation(LinearLayout.VERTICAL);TextView tvChange = new TextView(getContext());tvChange.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));tvChange.setText(text);tvChange.setTextSize(18);tvChange.setTextColor(Color.parseColor("#FF393939"));tvChange.setGravity(Gravity.CENTER);tvChange.setCompoundDrawablePadding(2);tvChange.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(drawId), null, null);llChange.addView(tvChange);return llChange;}private void addBottomView(boolean isLeft, LinearLayout view) {RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);lp.addRule(RelativeLayout.CENTER_VERTICAL);if (isLeft) {lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);lp.leftMargin = 88;} else {lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);lp.rightMargin = 88;}rlOperate.addView(view, lp);}private void initOther() {topEnter = new TranslateAnimation(0, 0, -100, 0);topEnter.setDuration(DURATION);topExit = new TranslateAnimation(0, 0, 0, -100);topExit.setDuration(DURATION);topExit.setAnimationListener(this);buttomEnter = new TranslateAnimation(0, 0, 300, 0);buttomEnter.setDuration(DURATION);buttomExit = new TranslateAnimation(0, 0, 0, 100);buttomExit.setDuration(DURATION);}@Overridepublic void onAnimationStart(Animation animation) {// do nothing}@Overridepublic void onAnimationEnd(Animation animation) {if (mRoot != null) {mRoot.setVisibility(View.GONE);}}@Overridepublic void onAnimationRepeat(Animation animation) {// do nothing}@Overridepublic void hide() {isShowing = false;llTitle.startAnimation(topExit);flOperate.startAnimation(buttomExit);}@Overridepublic void show() {if (!isShowing) {mRoot.setVisibility(View.VISIBLE);isShowing = true;llTitle.startAnimation(topEnter);flOperate.startAnimation(buttomEnter);}handler.removeCallbacks(this);handler.postDelayed(this, DELAYMILLIS);}@Overridepublic void run() {hide();}@Overridepublic void setTitle(String title) {if (tvTitle != null) {tvTitle.setText(title);}}@Overridepublic View getHangupView() {return llHangup;}@Overridepublic View getChangeView() {return llChange;}@Overridepublic boolean onTouch(View v, MotionEvent event) {show();return false;}}interface IVideoControlPanel {/** * 隐藏操作面板 */public void hide();/** * 显示操作面板 */public void show();/** * 设置标题 *  * @param title */public void setTitle(String title);/** * 获取挂断的View *  * @return */public View getHangupView();/** * 获取切换的View *  * @return */public View getChangeView();}




原创粉丝点击