【高仿微信系列】微信录制小视频
2015-10-19 17:19
555 查看
本帖最后由 ☂上官๑۩۞۩ 于 2015-7-15 17:14 编辑
[align=left]微信从6.0版本开始推出小视频功能,随着4G网络的出现,视频将会是一个趋势,他能表达出文字所不能表现的东西,增加了微信的黏性。还记得微信小视频这个功能一推出,如同病毒一样席卷朋友圈。[/align]
作为爱美的我们,怎么能把我们的窘态暴露给朋友圈的小伙伴呢,必须正能量!美好的!必须美化! So,录制小视频后,加各种滤镜,炫酷MV主题,妈妈再也不担心我的猪窝了…
“小视频”对于微信如此之重要。那么,如何实现呢?
先看下咱们的实现效果:
PS:gif 图片比较大,如果等不及的童鞋,可以点击这里查看视频
OK,先看下,消息列表页面的 下滑显示眼睛动画效果的实现方式:
自定义ListView:PullDownListView.java
PullDownListView来自guojunyi的分享, GitHub项目地址:点击这里
package com.example.wechat01.widght;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.RelativeLayout;
import com.example.wechat01.R;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
public class PullDownListView extends RelativeLayout implements
OnScrollListener {
static int MAX_PULL_TOP_HEIGHT;
static int MAX_PULL_BOTTOM_HEIGHT;
static int REFRESHING_TOP_HEIGHT;
static int REFRESHING_BOTTOM_HEIGHT;
private boolean isTop;
private boolean isBottom;
private boolean isRefreshing;
private boolean isAnimation;
RelativeLayout layoutHeader;
RelativeLayout layoutFooter;
private int mCurrentY = 0;
boolean pullTag = false;
OnScrollListener mOnScrollListener;
OnPullHeightChangeListener mOnPullHeightChangeListener;
public void setOnPullHeightChangeListener(
OnPullHeightChangeListener listener) {
this.mOnPullHeightChangeListener = listener;
}
public void setOnScrollListener(OnScrollListener listener) {
mOnScrollListener = listener;
}
public PullDownListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public boolean isRefreshing() {
return this.isRefreshing;
}
private ListView mListView = new ListView(getContext()) {
int lastY = 0;
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isAnimation || isRefreshing) {
return super.onTouchEvent(ev);
}
RelativeLayout parent = (RelativeLayout) mListView.getParent();
int currentY = (int) ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE: {
boolean isToBottom = currentY - lastY >= 0 ? true : false;
int step = Math.abs(currentY - lastY);
lastY = currentY;
if (isTop && mListView.getTop() >= 0) {
if (isToBottom && mListView.getTop() <= MAX_PULL_TOP_HEIGHT) {
MotionEvent event = MotionEvent.obtain(ev);
ev.setAction(MotionEvent.ACTION_UP);
super.onTouchEvent(ev);
pullTag = true;
if (mListView.getTop() > layoutHeader.getHeight()) {
step = step / 2;
}
if ((mListView.getTop() + step) > MAX_PULL_TOP_HEIGHT) {
mCurrentY = MAX_PULL_TOP_HEIGHT;
scrollTopTo(mCurrentY);
} else {
mCurrentY += step;
scrollTopTo(mCurrentY);
}
} else if (!isToBottom && mListView.getTop() > 0) {
MotionEvent event = MotionEvent.obtain(ev);
ev.setAction(MotionEvent.ACTION_UP);
super.onTouchEvent(ev);
if ((mListView.getTop() - step) < 0) {
mCurrentY = 0;
scrollTopTo(mCurrentY);
} else {
mCurrentY -= step;
scrollTopTo(mCurrentY);
}
} else if (!isToBottom && mListView.getTop() == 0) {
if (!pullTag) {
return super.onTouchEvent(ev);
}
}
return true;
} else if (isBottom
&& mListView.getBottom() <= parent.getHeight()) {
if (!isToBottom
&& (parent.getHeight() - mListView.getBottom()) <= MAX_PULL_BOTTOM_HEIGHT) {
MotionEvent event = MotionEvent.obtain(ev);
ev.setAction(MotionEvent.ACTION_UP);
super.onTouchEvent(ev);
pullTag = true;
if (parent.getHeight() - mListView.getBottom() > layoutFooter
.getHeight()) {
step = step / 2;
}
if ((mListView.getBottom() - step) < (parent
.getHeight() - MAX_PULL_BOTTOM_HEIGHT)) {
mCurrentY = -MAX_PULL_BOTTOM_HEIGHT;
scrollBottomTo(mCurrentY);
} else {
mCurrentY -= step;
scrollBottomTo(mCurrentY);
}
} else if (isToBottom
&& (mListView.getBottom() < parent.getHeight())) {
if ((mListView.getBottom() + step) > parent.getHeight()) {
mCurrentY = 0;
scrollBottomTo(mCurrentY);
} else {
mCurrentY += step;
scrollBottomTo(mCurrentY);
}
} else if (isToBottom
&& mListView.getBottom() == parent.getHeight()) {
if (!pullTag) {
return super.onTouchEvent(ev);
}
}
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
pullTag = false;
if (mListView.getTop() > 0) {
if (mListView.getTop() > REFRESHING_TOP_HEIGHT) {
animateTopTo(layoutHeader.getMeasuredHeight());
isRefreshing = true;
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onRefreshing(true);
}
} else {
animateTopTo(0);
}
} else if (mListView.getBottom() < parent.getHeight()) {
if ((parent.getHeight() - mListView.getBottom()) > REFRESHING_BOTTOM_HEIGHT) {
animateBottomTo(-layoutFooter.getMeasuredHeight());
isRefreshing = true;
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onRefreshing(false);
}
} else {
animateBottomTo(0);
}
}
}
return super.onTouchEvent(ev);
}
};
public void scrollBottomTo(int y) {
mListView.layout(mListView.getLeft(), y, mListView.getRight(),
this.getMeasuredHeight() + y);
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onBottomHeightChange(
layoutHeader.getHeight(), -y);
}
}
public void animateBottomTo(final int y) {
ValueAnimator animator = ValueAnimator.ofInt(mListView.getBottom()
- this.getMeasuredHeight(), y);
animator.setDuration(300);
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
int frameValue = (Integer) animation.getAnimatedValue();
mCurrentY = frameValue;
scrollBottomTo(frameValue);
if (frameValue == y) {
isAnimation = false;
}
}
});
isAnimation = true;
animator.start();
}
public void scrollTopTo(int y) {
mListView.layout(mListView.getLeft(), y, mListView.getRight(),
this.getMeasuredHeight() + y);
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onTopHeightChange(
layoutHeader.getHeight(), y);
}
}
public void animateTopTo(final int y) {
ValueAnimator animator = ValueAnimator.ofInt(mListView.getTop(), y);
animator.setDuration(300);
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
int frameValue = (Integer) animation.getAnimatedValue();
mCurrentY = frameValue;
scrollTopTo(frameValue);
if (frameValue == y) {
isAnimation = false;
}
}
});
isAnimation = true;
animator.start();
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
REFRESHING_TOP_HEIGHT = layoutHeader.getMeasuredHeight();
REFRESHING_BOTTOM_HEIGHT = layoutFooter.getMeasuredHeight();
MAX_PULL_TOP_HEIGHT = this.getMeasuredHeight();
MAX_PULL_BOTTOM_HEIGHT = this.getMeasuredHeight();
}
@Override
public void onFinishInflate() {
mListView.setBackgroundColor(0xffffffff);
mListView.setCacheColorHint(Color.TRANSPARENT);
mListView.setVerticalScrollBarEnabled(false);
mListView.setLayoutParams(new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mListView.setOnScrollListener(this);
mListView.setDividerHeight(0);
this.addView(mListView);
layoutHeader = (RelativeLayout) this.findViewById(R.id.layoutHeader);
layoutFooter = (RelativeLayout) this.findViewById(R.id.layoutFooter);
super.onFinishInflate();
}
public ListView getListView() {
return this.mListView;
}
public void pullUp() {
isRefreshing = false;
if (mListView.getTop() > 0) {
animateTopTo(0);
} else if (mListView.getBottom() < this.getHeight()) {
animateBottomTo(0);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (null != mOnScrollListener) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
if (mListView.getCount() > 0) {
if ((firstVisibleItem + visibleItemCount) == totalItemCount) {
View lastItem = (View) mListView
.getChildAt(visibleItemCount - 1);
if (null != lastItem) {
if (lastItem.getBottom() == mListView.getHeight()) {
Log.e("my", lastItem.getBottom() + "");
isBottom = true;
} else {
isBottom = false;
}
}
} else {
isBottom = false;
}
} else {
isBottom = false;
}
if (mListView.getCount() > 0) {
if (firstVisibleItem == 0) {
View firstItem = mListView.getChildAt(0);
if (null != firstItem) {
if (firstItem.getTop() == 0) {
isTop = true;
} else {
isTop = false;
}
}
} else {
isTop = false;
}
} else {
isTop = true;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if (null != mOnScrollListener) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
// listener call back
public interface OnPullHeightChangeListener {
public void onTopHeightChange(int headerHeight, int pullHeight);
public void onBottomHeightChange(int footerHeight, int pullHeight);
public void onRefreshing(boolean isTop);
}
}
复制代码
这个Demo比较复杂,具体实现方式请大家去Github研究一下代码吧~
另外还有视频录制这块的功能,有些复杂,这块是用的秒拍团队提供的视频录制SDK,感兴趣的可以去官网膜拜~
官网地址:
OK,项目的完整代码可以去 Github (点击这里) 下载。
Download Apk
Github项目地址:https://github.com/motianhuo/VCameraDemo
文章来自:达达的梦想的博客 http://blog.csdn.net/zhaiyuanjun
[align=left]微信从6.0版本开始推出小视频功能,随着4G网络的出现,视频将会是一个趋势,他能表达出文字所不能表现的东西,增加了微信的黏性。还记得微信小视频这个功能一推出,如同病毒一样席卷朋友圈。[/align]
作为爱美的我们,怎么能把我们的窘态暴露给朋友圈的小伙伴呢,必须正能量!美好的!必须美化! So,录制小视频后,加各种滤镜,炫酷MV主题,妈妈再也不担心我的猪窝了…
“小视频”对于微信如此之重要。那么,如何实现呢?
先看下咱们的实现效果:
PS:gif 图片比较大,如果等不及的童鞋,可以点击这里查看视频
OK,先看下,消息列表页面的 下滑显示眼睛动画效果的实现方式:
自定义ListView:PullDownListView.java
PullDownListView来自guojunyi的分享, GitHub项目地址:点击这里
package com.example.wechat01.widght;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.RelativeLayout;
import com.example.wechat01.R;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
public class PullDownListView extends RelativeLayout implements
OnScrollListener {
static int MAX_PULL_TOP_HEIGHT;
static int MAX_PULL_BOTTOM_HEIGHT;
static int REFRESHING_TOP_HEIGHT;
static int REFRESHING_BOTTOM_HEIGHT;
private boolean isTop;
private boolean isBottom;
private boolean isRefreshing;
private boolean isAnimation;
RelativeLayout layoutHeader;
RelativeLayout layoutFooter;
private int mCurrentY = 0;
boolean pullTag = false;
OnScrollListener mOnScrollListener;
OnPullHeightChangeListener mOnPullHeightChangeListener;
public void setOnPullHeightChangeListener(
OnPullHeightChangeListener listener) {
this.mOnPullHeightChangeListener = listener;
}
public void setOnScrollListener(OnScrollListener listener) {
mOnScrollListener = listener;
}
public PullDownListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public boolean isRefreshing() {
return this.isRefreshing;
}
private ListView mListView = new ListView(getContext()) {
int lastY = 0;
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isAnimation || isRefreshing) {
return super.onTouchEvent(ev);
}
RelativeLayout parent = (RelativeLayout) mListView.getParent();
int currentY = (int) ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE: {
boolean isToBottom = currentY - lastY >= 0 ? true : false;
int step = Math.abs(currentY - lastY);
lastY = currentY;
if (isTop && mListView.getTop() >= 0) {
if (isToBottom && mListView.getTop() <= MAX_PULL_TOP_HEIGHT) {
MotionEvent event = MotionEvent.obtain(ev);
ev.setAction(MotionEvent.ACTION_UP);
super.onTouchEvent(ev);
pullTag = true;
if (mListView.getTop() > layoutHeader.getHeight()) {
step = step / 2;
}
if ((mListView.getTop() + step) > MAX_PULL_TOP_HEIGHT) {
mCurrentY = MAX_PULL_TOP_HEIGHT;
scrollTopTo(mCurrentY);
} else {
mCurrentY += step;
scrollTopTo(mCurrentY);
}
} else if (!isToBottom && mListView.getTop() > 0) {
MotionEvent event = MotionEvent.obtain(ev);
ev.setAction(MotionEvent.ACTION_UP);
super.onTouchEvent(ev);
if ((mListView.getTop() - step) < 0) {
mCurrentY = 0;
scrollTopTo(mCurrentY);
} else {
mCurrentY -= step;
scrollTopTo(mCurrentY);
}
} else if (!isToBottom && mListView.getTop() == 0) {
if (!pullTag) {
return super.onTouchEvent(ev);
}
}
return true;
} else if (isBottom
&& mListView.getBottom() <= parent.getHeight()) {
if (!isToBottom
&& (parent.getHeight() - mListView.getBottom()) <= MAX_PULL_BOTTOM_HEIGHT) {
MotionEvent event = MotionEvent.obtain(ev);
ev.setAction(MotionEvent.ACTION_UP);
super.onTouchEvent(ev);
pullTag = true;
if (parent.getHeight() - mListView.getBottom() > layoutFooter
.getHeight()) {
step = step / 2;
}
if ((mListView.getBottom() - step) < (parent
.getHeight() - MAX_PULL_BOTTOM_HEIGHT)) {
mCurrentY = -MAX_PULL_BOTTOM_HEIGHT;
scrollBottomTo(mCurrentY);
} else {
mCurrentY -= step;
scrollBottomTo(mCurrentY);
}
} else if (isToBottom
&& (mListView.getBottom() < parent.getHeight())) {
if ((mListView.getBottom() + step) > parent.getHeight()) {
mCurrentY = 0;
scrollBottomTo(mCurrentY);
} else {
mCurrentY += step;
scrollBottomTo(mCurrentY);
}
} else if (isToBottom
&& mListView.getBottom() == parent.getHeight()) {
if (!pullTag) {
return super.onTouchEvent(ev);
}
}
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
pullTag = false;
if (mListView.getTop() > 0) {
if (mListView.getTop() > REFRESHING_TOP_HEIGHT) {
animateTopTo(layoutHeader.getMeasuredHeight());
isRefreshing = true;
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onRefreshing(true);
}
} else {
animateTopTo(0);
}
} else if (mListView.getBottom() < parent.getHeight()) {
if ((parent.getHeight() - mListView.getBottom()) > REFRESHING_BOTTOM_HEIGHT) {
animateBottomTo(-layoutFooter.getMeasuredHeight());
isRefreshing = true;
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onRefreshing(false);
}
} else {
animateBottomTo(0);
}
}
}
return super.onTouchEvent(ev);
}
};
public void scrollBottomTo(int y) {
mListView.layout(mListView.getLeft(), y, mListView.getRight(),
this.getMeasuredHeight() + y);
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onBottomHeightChange(
layoutHeader.getHeight(), -y);
}
}
public void animateBottomTo(final int y) {
ValueAnimator animator = ValueAnimator.ofInt(mListView.getBottom()
- this.getMeasuredHeight(), y);
animator.setDuration(300);
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
int frameValue = (Integer) animation.getAnimatedValue();
mCurrentY = frameValue;
scrollBottomTo(frameValue);
if (frameValue == y) {
isAnimation = false;
}
}
});
isAnimation = true;
animator.start();
}
public void scrollTopTo(int y) {
mListView.layout(mListView.getLeft(), y, mListView.getRight(),
this.getMeasuredHeight() + y);
if (null != mOnPullHeightChangeListener) {
mOnPullHeightChangeListener.onTopHeightChange(
layoutHeader.getHeight(), y);
}
}
public void animateTopTo(final int y) {
ValueAnimator animator = ValueAnimator.ofInt(mListView.getTop(), y);
animator.setDuration(300);
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
int frameValue = (Integer) animation.getAnimatedValue();
mCurrentY = frameValue;
scrollTopTo(frameValue);
if (frameValue == y) {
isAnimation = false;
}
}
});
isAnimation = true;
animator.start();
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
REFRESHING_TOP_HEIGHT = layoutHeader.getMeasuredHeight();
REFRESHING_BOTTOM_HEIGHT = layoutFooter.getMeasuredHeight();
MAX_PULL_TOP_HEIGHT = this.getMeasuredHeight();
MAX_PULL_BOTTOM_HEIGHT = this.getMeasuredHeight();
}
@Override
public void onFinishInflate() {
mListView.setBackgroundColor(0xffffffff);
mListView.setCacheColorHint(Color.TRANSPARENT);
mListView.setVerticalScrollBarEnabled(false);
mListView.setLayoutParams(new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mListView.setOnScrollListener(this);
mListView.setDividerHeight(0);
this.addView(mListView);
layoutHeader = (RelativeLayout) this.findViewById(R.id.layoutHeader);
layoutFooter = (RelativeLayout) this.findViewById(R.id.layoutFooter);
super.onFinishInflate();
}
public ListView getListView() {
return this.mListView;
}
public void pullUp() {
isRefreshing = false;
if (mListView.getTop() > 0) {
animateTopTo(0);
} else if (mListView.getBottom() < this.getHeight()) {
animateBottomTo(0);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (null != mOnScrollListener) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
if (mListView.getCount() > 0) {
if ((firstVisibleItem + visibleItemCount) == totalItemCount) {
View lastItem = (View) mListView
.getChildAt(visibleItemCount - 1);
if (null != lastItem) {
if (lastItem.getBottom() == mListView.getHeight()) {
Log.e("my", lastItem.getBottom() + "");
isBottom = true;
} else {
isBottom = false;
}
}
} else {
isBottom = false;
}
} else {
isBottom = false;
}
if (mListView.getCount() > 0) {
if (firstVisibleItem == 0) {
View firstItem = mListView.getChildAt(0);
if (null != firstItem) {
if (firstItem.getTop() == 0) {
isTop = true;
} else {
isTop = false;
}
}
} else {
isTop = false;
}
} else {
isTop = true;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if (null != mOnScrollListener) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
// listener call back
public interface OnPullHeightChangeListener {
public void onTopHeightChange(int headerHeight, int pullHeight);
public void onBottomHeightChange(int footerHeight, int pullHeight);
public void onRefreshing(boolean isTop);
}
}
复制代码
这个Demo比较复杂,具体实现方式请大家去Github研究一下代码吧~
另外还有视频录制这块的功能,有些复杂,这块是用的秒拍团队提供的视频录制SDK,感兴趣的可以去官网膜拜~
官网地址:
OK,项目的完整代码可以去 Github (点击这里) 下载。
Download Apk
Github项目地址:https://github.com/motianhuo/VCameraDemo
文章来自:达达的梦想的博客 http://blog.csdn.net/zhaiyuanjun
相关文章推荐
- iOS 9系统策略更新,微信分享无法使用解决办法
- 微信订阅返回消息
- Android 微信登陆
- 微信公众号接入
- 微信高级群发接口 {"errcode":40008,"errmsg":"invalid message type hint: [aRIDBA0726age9]"}
- 微信分享核心代码
- 关于微信分享、微信登录秘钥问题,及点击分享闪一下,提示分享成功,实际上没有分享成功
- 微信自定义菜单view类型获取openid访问网页
- java50个小程序
- 微信企业号开发:微信考勤百度地图定位,错误修正
- Android打开指定程序(微博/微信/人人等)
- 微公众号开发
- iOS 通过分类实现 微信的导航栏"加载中..."
- Android: 实现类似QQ、微信的表情输入键盘
- 微信企业号api调用频率
- 企业微信公众平台订阅号运营11大技巧
- ios9 qq微信微博等分享用不了的解决方案
- ios 微信分享审核上架注意事项
- android 微信分享功能
- 简单的JAVA小程序(计算器)