由于所在的公司比较注重项目安全性,所以在项目同步这块几乎没有涉足,乘工作之余敲一个简单的app,起名为EasyLive,目的于熟悉一些工作之外的有趣知识点和巩固自己的基础知识。
以打造一款兼容性较为完整的android万能播放器为基础,后期再不断的添加一些生活中有趣的功能点,并不定期的将项目同步到github上,以供大家共同修改和指教。
集成准备------------------------------------------------------------------------------1
前端UI设计---------------------------------------------------------------------------2
动画菜单、图标拖拽、图片滑动、自定义scrollview等模块处理--------3
习惯性的用eclipse,不知道是自己真的老了,还是eclipse打包出来的apk总是比AS小的原因,需要AS源码的朋友记得Q我哈,或者来个大神直接贡献到git上与我们一起分享(地址)。
package com.minghui.easyapp.scrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
public class ObserveScrollView extends ScrollView {
private ScrollListener mListener;
public static interface ScrollListener {// 声明接口,用于传递数据
public void scrollOritention(int l, int t, int oldl, int oldt);
}
public ObserveScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public ObserveScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ObserveScrollView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
super.onScrollChanged(l, t, oldl, oldt);
if (mListener != null) {
mListener.scrollOritention(l, t, oldl, oldt);
}
}
public void setScrollListener(ScrollListener l) {
this.mListener = l;
}
}
//主要代码
public boolean createReflectedImages() {
// The gap we want between the reflection and the original image
final int reflectionGap = 4;
int index = 0;
for (int imageId : mImageIds) {
Bitmap originalImage = BitmapFactory.decodeResource(
mContext.getResources(), imageId);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matrix applied to it.
// We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit
// reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
// Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap,
deafaultPaint);
// Draw in the reflection
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the
// reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap,
0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
BitmapDrawable bd = new BitmapDrawable(bitmapWithReflection);
bd.setAntiAlias(true);
ImageView imageView = new ImageView(mContext);
// imageView.setImageBitmap(bitmapWithReflection);
imageView.setImageDrawable(bd);
imageView.setLayoutParams(new GalleryFlow.LayoutParams(280, 460));
imageView.setPadding(0, 40, 0, 0);
// imageView.setScaleType(ScaleType.MATRIX);
mImages[index++] = imageView;
}
return true;
}
package com.minghui.easyapp.dragview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;
/**
* 随意拖动的view
*/
@SuppressLint("AppCompatCustomView")
public class DragView extends ImageView {
private int width;
private int height;
private int screenWidth;
private int screenHeight;
private Context context;
// 是否拖动
private boolean isDrag = false;
public boolean isDrag() {
return isDrag;
}
public DragView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
screenWidth = ScreenUtil.getScreenWidth(context);
screenHeight = ScreenUtil.getScreenHeight(context)
- getStatusBarHeight();
}
public int getStatusBarHeight() {
int resourceId = getResources().getIdentifier("status_bar_height",
"dimen", "android");
return getResources().getDimensionPixelSize(resourceId);
}
private float downX;
private float downY;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (this.isEnabled()) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrag = false;
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
Log.e("kid", "ACTION_MOVE");
final float xDistance = event.getX() - downX;
final float yDistance = event.getY() - downY;
int l,
r,
t,
b;
// 当水平或者垂直滑动距离大于10,才算拖动事件
if (Math.abs(xDistance) > 10 || Math.abs(yDistance) > 10) {
Log.e("kid", "Drag");
isDrag = true;
l = (int) (getLeft() + xDistance);
r = l + width;
t = (int) (getTop() + yDistance);
b = t + height;
// 不划出边界判断,此处应按照项目实际情况,因为本项目需求移动的位置是手机全屏,
// 所以才能这么写,如果是固定区域,要得到父控件的宽高位置后再做处理
if (l < 0) {
l = 0;
r = l + width;
} else if (r > screenWidth) {
r = screenWidth;
l = r - width;
}
if (t < 0) {
t = 0;
b = t + height;
} else if (b > screenHeight) {
b = screenHeight;
t = b - height;
}
this.layout(l, t, r, b);
}
break;
case MotionEvent.ACTION_UP:
setPressed(false);
break;
case MotionEvent.ACTION_CANCEL:
setPressed(false);
break;
}
return true;
}
return false;
}
}
package com.minghui.easyapp.utils;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.BounceInterpolator;
public class NvaAnimator {
/**
* 打开菜单 view:动画控件 index:第几个控件 num:有几个控件 radius:扇形半径
*/
public static void openAnim(View view, int index, int num, int radius,
boolean isRadians) {
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
final int translationX;
final int translationY;
if (isRadians) {
double angle = Math.toRadians(180) / (num - 1) * index;
translationX = -(int) (radius * Math.cos(angle));
translationY = -(int) (radius * Math.sin(angle));
} else {
translationX = index * 80 + 20 * index;
translationY = 0;
}
ObjectAnimator one = ObjectAnimator.ofFloat(view, "translationX", 0,
translationX);
ObjectAnimator two = ObjectAnimator.ofFloat(view, "translationY", 0,
translationY);
ObjectAnimator three = ObjectAnimator.ofFloat(view, "rotation", 0, 360);
ObjectAnimator four = ObjectAnimator.ofFloat(view, "scaleX", 0f, 1f);
ObjectAnimator five = ObjectAnimator.ofFloat(view, "scaleY", 0f, 1f);
ObjectAnimator six = ObjectAnimator.ofFloat(view, "alpha", 0f, 1);
AnimatorSet set = new AnimatorSet();
if (isRadians) {
set.playTogether(one, two, three, four, five, six);
} else {
set.playTogether(one, two, six);
}
set.setDuration(2000);
// 回弹效果
set.setInterpolator(new BounceInterpolator());
set.start();
}
/**
* 关闭扇形菜单
*
* @param view
* @param index
* @param num
* @param radius
*/
public static void closeAnim(View view, int index, int num, int radius,
boolean isRadians) {
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
final int translationX;
final int translationY;
if (isRadians) {
double angle = Math.toRadians(180) / (num - 1) * index;
translationX = -(int) (radius * Math.cos(angle));
translationY = -(int) (radius * Math.sin(angle));
} else {
translationX = index * 80 + 20 * index;
translationY = 0;
}
ObjectAnimator one = ObjectAnimator.ofFloat(view, "translationX",
translationX, 0);
ObjectAnimator two = ObjectAnimator.ofFloat(view, "translationY",
translationY, 0);
ObjectAnimator three = ObjectAnimator.ofFloat(view, "rotation", 0, 360);
ObjectAnimator four = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f);
ObjectAnimator five = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f);
ObjectAnimator six = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);
AnimatorSet set = new AnimatorSet();
if (isRadians) {
set.playTogether(one, two, three, four, five, six);
} else {
set.playTogether(one, two, six);
}
set.setDuration(2000);
// 回弹效果
set.setInterpolator(new BounceInterpolator());
set.start();
}
}
//判断是否有前摄像头
@TargetApi(9)
private int FindFrontCamera() {
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); // get cameras number
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { // ��������ͷ�ķ�λ��Ŀǰ�ж���ֵ�����ֱ�ΪCAMERA_FACING_FRONTǰ�ú�CAMERA_FACING_BACK����
return camIdx;
}
}
return -1;
}
//判断是否有后摄像头
@TargetApi(9)
private int FindBackCamera() {
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); // get cameras number
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { // ��������ͷ�ķ�λ��Ŀǰ�ж���ֵ�����ֱ�ΪCAMERA_FACING_FRONTǰ�ú�CAMERA_FACING_BACK����
return camIdx;
}
}
return -1;
}
/**
* 根据横竖屏自动调节preview方向,Starting from API level 14, this method can be called
* when preview is active.
*
* @param activity
* @param cameraId
* @param camera
*/
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
// degrees the angle that the picture will be rotated clockwise. Valid
// values are 0, 90, 180, and 270.
// The starting position is 0 (landscape).
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else {
// back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
20181219第二版demo---添加了扇形动画菜单+自由拖拽图标+3D图片滑动倾斜放大倒影+自定义scrollview实现滑动监听等。
这里是项目更新demo:https://github.com/Life1412378121/EasyLive
THE END 感谢您的查看,如喜欢,欢迎您的star/fork ,小菜我叫吴明辉,期待与您一同打造一个无广告甚至免费的万能播放器。