diff --git a/PLDroidShortVideoDemo/app/build.gradle b/PLDroidShortVideoDemo/app/build.gradle index 447d31b..1e79cfc 100644 --- a/PLDroidShortVideoDemo/app/build.gradle +++ b/PLDroidShortVideoDemo/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.qiniu.pili.droid.shortvideo.demo" minSdkVersion 18 targetSdkVersion 25 - versionCode 14 - versionName "1.9.0" + versionCode 15 + versionName "1.10.0" multiDexEnabled true buildConfigField "long", "BUILD_TIMESTAMP", System.currentTimeMillis() + "L" ndk { @@ -32,7 +32,7 @@ android { dependencies { compile 'com.qiniu:qiniu-android-sdk:7.3.10' - compile files('libs/pldroid-shortvideo-1.9.0.jar') + compile files('libs/pldroid-shortvideo-1.10.0.jar') compile files('libs/pldroid-player-2.0.5.jar') compile files('libs/EasyAR.jar') compile files('libs/EasyAR3D.jar') @@ -52,4 +52,5 @@ dependencies { compile files('libs/TuSDKFace-1.0.0.jar') compile files('libs/TuSDKVideo-1.11.0.jar') compile files('libs/universal-image-loader-1.9.4.jar') + compile 'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.10.6' } \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/libs/pldroid-shortvideo-1.10.0.jar b/PLDroidShortVideoDemo/app/libs/pldroid-shortvideo-1.10.0.jar new file mode 100644 index 0000000..d0ef0d7 Binary files /dev/null and b/PLDroidShortVideoDemo/app/libs/pldroid-shortvideo-1.10.0.jar differ diff --git a/PLDroidShortVideoDemo/app/libs/pldroid-shortvideo-1.9.0.jar b/PLDroidShortVideoDemo/app/libs/pldroid-shortvideo-1.9.0.jar deleted file mode 100644 index df6915f..0000000 Binary files a/PLDroidShortVideoDemo/app/libs/pldroid-shortvideo-1.9.0.jar and /dev/null differ diff --git a/PLDroidShortVideoDemo/app/src/main/AndroidManifest.xml b/PLDroidShortVideoDemo/app/src/main/AndroidManifest.xml index fbe57b6..cabc18b 100644 --- a/PLDroidShortVideoDemo/app/src/main/AndroidManifest.xml +++ b/PLDroidShortVideoDemo/app/src/main/AndroidManifest.xml @@ -14,10 +14,10 @@ @@ -27,8 +27,7 @@ - + @@ -72,11 +71,23 @@ + android:theme="@style/AppTheme" /> + + + diff --git a/PLDroidShortVideoDemo/app/src/main/assets/fonts/HappyZcool-2016.ttf b/PLDroidShortVideoDemo/app/src/main/assets/fonts/HappyZcool-2016.ttf new file mode 100644 index 0000000..ba2ad8a Binary files /dev/null and b/PLDroidShortVideoDemo/app/src/main/assets/fonts/HappyZcool-2016.ttf differ diff --git a/PLDroidShortVideoDemo/app/src/main/assets/fonts/zcool-gdh.ttf b/PLDroidShortVideoDemo/app/src/main/assets/fonts/zcool-gdh.ttf new file mode 100644 index 0000000..ee49dea Binary files /dev/null and b/PLDroidShortVideoDemo/app/src/main/assets/fonts/zcool-gdh.ttf differ diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/ArRecordActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/ArRecordActivity.java index bdffa47..cc81b2c 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/ArRecordActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/ArRecordActivity.java @@ -180,8 +180,8 @@ private void initview() { } private String prepareUrl() { - String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()); - String fileName = "EasyAR_Recording_" + timeStamp + ".mp4"; + String timestamp = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()); + String fileName = "EasyAR_Recording_" + timestamp + ".mp4"; File folder = new File(Config.VIDEO_STORAGE_DIR + "ArMovies"); if (!folder.exists()) folder.mkdirs(); diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/MainActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/MainActivity.java index 4cd2014..09b0d34 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/MainActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/MainActivity.java @@ -133,6 +133,12 @@ public void onClickAR(View v) { } } + public void onClickTransitionMake(View v) { + if (isPermissionOK()) { + jumpToActivity(VideoDivideActivity.class); + } + } + public void onClickDraftBox(View v) { if (isPermissionOK()) { jumpToActivity(DraftBoxActivity.class); diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/TransitionMakeActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/TransitionMakeActivity.java new file mode 100644 index 0000000..abec724 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/TransitionMakeActivity.java @@ -0,0 +1,233 @@ +package com.qiniu.pili.droid.shortvideo.demo.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.PLVideoSaveListener; +import com.qiniu.pili.droid.shortvideo.demo.R; +import com.qiniu.pili.droid.shortvideo.demo.transition.Transition0; +import com.qiniu.pili.droid.shortvideo.demo.transition.Transition1; +import com.qiniu.pili.droid.shortvideo.demo.transition.Transition2; +import com.qiniu.pili.droid.shortvideo.demo.transition.Transition3; +import com.qiniu.pili.droid.shortvideo.demo.transition.Transition4; +import com.qiniu.pili.droid.shortvideo.demo.transition.Transition5; +import com.qiniu.pili.droid.shortvideo.demo.transition.TransitionBase; +import com.qiniu.pili.droid.shortvideo.demo.utils.ToastUtils; +import com.qiniu.pili.droid.shortvideo.demo.view.CustomProgressDialog; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionEditView; + +import java.lang.reflect.Constructor; + +import static com.qiniu.pili.droid.shortvideo.demo.activity.VideoFrameActivity.DATA_EXTRA_PATH; +import static com.qiniu.pili.droid.shortvideo.demo.utils.Config.VIDEO_STORAGE_DIR; + +public class TransitionMakeActivity extends Activity { + private static final String TAG = "TransitionMakeActivity"; + + private static String[] TRANSITION_TITLE = { + "大标题", "章节", "简约", "引用", "标题与副标题", "片尾" + }; + private static Class[] TRANSITION_CLASS = { + Transition0.class, Transition1.class, Transition2.class, Transition3.class, Transition4.class, Transition5.class + }; + + private RecyclerView mTransListView; + private CustomProgressDialog mProcessingDialog; + + private TransitionBase[] mTransitions = new TransitionBase[6]; + private TransitionBase mCurTransition; + private TransitionEditView mTransEditView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_transition); + + initTransitions(); + + mTransListView = (RecyclerView) findViewById(R.id.recycler_transition); + mTransEditView = (TransitionEditView) findViewById(R.id.transition_edit_view); + + LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); + mTransListView.setLayoutManager(layoutManager); + mTransListView.setAdapter(new TransListAdapter()); + + //consumed the event + mTransEditView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + + mProcessingDialog = new CustomProgressDialog(this); + mProcessingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + mCurTransition.cancelSave(); + } + }); + } + + private void initTransitions() { + final PLVideoEncodeSetting setting = new PLVideoEncodeSetting(TransitionMakeActivity.this); + setting.setEncodingSizeLevel(PLVideoEncodeSetting.VIDEO_ENCODING_SIZE_LEVEL.VIDEO_ENCODING_SIZE_LEVEL_720P_3); + for (int i = 0; i < mTransitions.length; i++) { + final ViewGroup viewGroup = (ViewGroup) findViewById(getResources().getIdentifier("transition_container" + i, "id", getPackageName())); + final int index = i; + viewGroup.post(new Runnable() { + @Override + public void run() { + try { + Constructor constructor = TRANSITION_CLASS[index].getConstructor(ViewGroup.class, PLVideoEncodeSetting.class); + TransitionBase transition = (TransitionBase) constructor.newInstance(viewGroup, setting); + + mTransitions[index] = transition; + + //default show first transition + if (index == 0) { + transition.setVisibility(View.VISIBLE); + mCurTransition = transition; + mTransEditView.setTransition(mCurTransition); + } else { + transition.setVisibility(View.INVISIBLE); + } + } catch (Exception e) { + e.printStackTrace(); + ToastUtils.s(TransitionMakeActivity.this, "Can not init Transition : " + "Transition" + index); + } + } + }); + } + } + + public void onBackClicked(View view) { + finish(); + } + + public void onSaveClicked(View view) { + mProcessingDialog.show(); + String path = VIDEO_STORAGE_DIR + "pl-transition-" + System.currentTimeMillis() + ".mp4"; + + mCurTransition.save(path, new PLVideoSaveListener() { + @Override + public void onSaveVideoSuccess(final String destFile) { + Log.i(TAG, "save success: " + destFile); + runOnUiThread(new Runnable() { + @Override + public void run() { + mProcessingDialog.dismiss(); + + Intent intent = new Intent(); + intent.putExtra(DATA_EXTRA_PATH, destFile); + setResult(VideoFrameActivity.TRANSITION_REQUEST_CODE, intent); + finish(); + } + }); + } + + @Override + public void onSaveVideoFailed(int errorCode) { + } + + @Override + public void onSaveVideoCanceled() { + } + + @Override + public void onProgressUpdate(final float percentage) { + runOnUiThread(new Runnable() { + @Override + public void run() { + mProcessingDialog.setProgress((int) (100 * percentage)); + } + }); + } + }); + } + + public void onEditClicked(View view) { + mTransEditView.setVisibility(View.VISIBLE); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + for (int i = 0; i < mTransitions.length; i++) { + mTransitions[i].destroy(); + } + } + + @Override + public void onBackPressed() { + if (mTransEditView.getVisibility() == View.VISIBLE) { + mTransEditView.setVisibility(View.GONE); + } else { + finish(); + } + } + + private class TransViewHolder extends RecyclerView.ViewHolder { + public TextView mTitle; + public View mItemView; + + public TransViewHolder(View itemView) { + super(itemView); + mItemView = itemView; + mTitle = (TextView) itemView.findViewById(R.id.title_text); + } + } + + private class TransListAdapter extends RecyclerView.Adapter { + private View mSelectedView; + + @Override + public TransViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + Context context = parent.getContext(); + LayoutInflater inflater = LayoutInflater.from(context); + View contactView = inflater.inflate(R.layout.item_transition_selector, parent, false); + TransViewHolder viewHolder = new TransViewHolder(contactView); + return viewHolder; + } + + @Override + public void onBindViewHolder(final TransViewHolder holder, final int position) { + holder.mTitle.setText(TRANSITION_TITLE[position]); + holder.mItemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mSelectedView != null) { + mSelectedView.setSelected(false); + } + holder.mItemView.setSelected(true); + mSelectedView = holder.mItemView; + + for (int i = 0; i < mTransitions.length; i++) { + mTransitions[i].setVisibility(View.GONE); + } + mTransitions[position].setVisibility(View.VISIBLE); + mTransitions[position].play(); + mCurTransition = mTransitions[position]; + mTransEditView.setTransition(mCurTransition); + } + }); + } + + @Override + public int getItemCount() { + return TRANSITION_TITLE.length; + } + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoComposeActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoComposeActivity.java index 8926113..781738d 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoComposeActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoComposeActivity.java @@ -130,11 +130,14 @@ public void onClickCompose(View v) { ToastUtils.s(this, "请先添加至少 2 个视频"); return; } - mProcessingDialog.show(); PLVideoEncodeSetting setting = new PLVideoEncodeSetting(this); setting.setEncodingSizeLevel(getEncodingSizeLevel(mEncodingSizeLevelSpinner.getSelectedItemPosition())); setting.setEncodingBitrate(getEncodingBitrateLevel(mEncodingBitrateLevelSpinner.getSelectedItemPosition())); - mShortVideoComposer.composeVideos(videos, Config.COMPOSE_FILE_PATH, setting, mVideoSaveListener); + if (mShortVideoComposer.composeVideos(videos, Config.COMPOSE_FILE_PATH, setting, mVideoSaveListener)) { + mProcessingDialog.show(); + } else { + ToastUtils.s(this, "开始拼接失败!"); + } } private PLVideoSaveListener mVideoSaveListener = new PLVideoSaveListener() { diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoDivideActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoDivideActivity.java new file mode 100644 index 0000000..66fc755 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoDivideActivity.java @@ -0,0 +1,597 @@ +package com.qiniu.pili.droid.shortvideo.demo.activity; + + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.MediaPlayer; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.GestureDetector; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.VideoView; + +import com.qiniu.pili.droid.shortvideo.PLMediaFile; +import com.qiniu.pili.droid.shortvideo.PLShortVideoTrimmer; +import com.qiniu.pili.droid.shortvideo.PLVideoFrame; +import com.qiniu.pili.droid.shortvideo.PLVideoSaveListener; +import com.qiniu.pili.droid.shortvideo.demo.R; +import com.qiniu.pili.droid.shortvideo.demo.utils.GetPathFromUri; +import com.qiniu.pili.droid.shortvideo.demo.view.CustomProgressDialog; +import com.qiniu.pili.droid.shortvideo.demo.view.FrameSelectorView; +import com.qiniu.pili.droid.shortvideo.demo.view.ObservableHorizontalScrollView; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Timer; +import java.util.TimerTask; + +import static com.qiniu.pili.droid.shortvideo.demo.activity.VideoFrameActivity.DATA_EXTRA_JUMP; +import static com.qiniu.pili.droid.shortvideo.demo.activity.VideoFrameActivity.DATA_EXTRA_PATHS; +import static com.qiniu.pili.droid.shortvideo.demo.utils.Config.VIDEO_STORAGE_DIR; + +public class VideoDivideActivity extends Activity { + private static final String TAG = "VideoDivideActivity"; + + private PLShortVideoTrimmer mShortVideoTrimmer; + private PLMediaFile mMediaFile; + + private CustomProgressDialog mProcessingDialog; + private VideoView mPreview; + private RecyclerView mFrameList; + private ViewGroup mFrameListParent; + private ObservableHorizontalScrollView mScrollView; + private FrameLayout mScrollViewParent; + private ImageButton mPlaybackButton; + private FrameSelectorView mCurSelectorView; + + private long mDurationMs; + private int mVideoFrameCount; + private long mShowFrameIntervalMs; + private String mSrcVideoPath; + + private FrameListAdapter mFrameListAdapter; + + private int mFrameWidth; + private int mFrameHeight; + private int mCurTrimNum; + + private ArrayList mSectionList = new ArrayList<>(); + private ArrayList mPathList = new ArrayList<>(); + + private TimerTask mScrollTimerTask; + private Timer mScrollTimer; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + + mProcessingDialog = new CustomProgressDialog(this); + mProcessingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + mShortVideoTrimmer.cancelTrim(); + } + }); + + Intent intent = new Intent(); + if (Build.VERSION.SDK_INT < 19) { + intent.setAction(Intent.ACTION_GET_CONTENT); + intent.setType("video/*"); + } else { + intent.setAction(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("video/*"); + } + startActivityForResult(Intent.createChooser(intent, "选择要导入的视频"), 0); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK) { + mSrcVideoPath = GetPathFromUri.getPath(this, data.getData()); + Log.i(TAG, "Select file: " + mSrcVideoPath); + if (mSrcVideoPath != null && !"".equals(mSrcVideoPath)) { + init(); + } + } else { + finish(); + } + } + + @Override + protected void onResume() { + super.onResume(); + play(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mScrollTimer != null) { + mScrollTimer.cancel(); + mScrollTimer = null; + } + if (mScrollTimerTask != null) { + mScrollTimerTask.cancel(); + mScrollTimerTask = null; + } + } + + public void onClickBack(View view) { + finish(); + } + + public void onClickDone(View view) { + resetData(); + if (mSectionList.size() > 0) { + trimOnce(); + } else { + noTrimJump(); + } + } + + public void onClickAdd(View view) { + pausePlayback(); + addSelectedRect(); + addSelectorView(); + } + + public void onClickPlayback(View view) { + if (mPreview.isPlaying()) { + pausePlayback(); + } else { + startPlayback(); + } + } + + private void init() { + initView(); + initMediaInfo(); + initVideoPlayer(); + initFrameList(); + initTimerTask(); + } + + private void initView() { + setContentView(R.layout.activity_video_divide); + + mPreview = (VideoView) findViewById(R.id.preview); + mPlaybackButton = (ImageButton) findViewById(R.id.pause_playback); + mFrameListParent = (ViewGroup) findViewById(R.id.recycler_parent); + mFrameList = (RecyclerView) findViewById(R.id.recycler_frame_list); + mScrollViewParent = (FrameLayout) findViewById(R.id.scroll_view_parent); + mScrollView = (ObservableHorizontalScrollView) findViewById(R.id.scroll_view); + + ImageView middleLineImage = (ImageView) findViewById(R.id.middle_line_image); + ViewGroup topGroup = (ViewGroup) findViewById(R.id.top_group); + + WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); + mFrameWidth = mFrameHeight = wm.getDefaultDisplay().getWidth() / 6; + middleLineImage.getLayoutParams().height = mFrameHeight; + + mScrollView.setOnScrollListener(new OnViewScrollListener()); + topGroup.setOnTouchListener(new OnTopViewTouchListener()); + } + + private void initMediaInfo() { + mMediaFile = new PLMediaFile(mSrcVideoPath); + mDurationMs = mMediaFile.getDurationMs(); + // if the duration time > 10s, the interval time is 3s, else is 1s + mShowFrameIntervalMs = (mDurationMs >= 1000 * 10) ? 3000 : 1000; + Log.i(TAG, "video duration: " + mDurationMs); + mVideoFrameCount = mMediaFile.getVideoFrameCount(false); + Log.i(TAG, "video frame count: " + mVideoFrameCount); + } + + private void initVideoPlayer() { + mPreview.setVideoPath(mSrcVideoPath); + mPreview.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + play(); + } + }); + play(); + } + + private void initTimerTask() { + mScrollTimerTask = new TimerTask() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + final int position = mPreview.getCurrentPosition(); + if (mPreview.isPlaying()) { + scrollToTime(position); + } + } + }); + } + }; + mScrollTimer = new Timer(); + // scroll fps:20 + mScrollTimer.schedule(mScrollTimerTask, 50, 50); + } + + private void initFrameList() { + mFrameListAdapter = new FrameListAdapter(); + mFrameList.setAdapter(mFrameListAdapter); + mFrameList.setItemViewCacheSize(getShowFrameCount()); + LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); + mFrameList.setLayoutManager(layoutManager); + } + + private void resetData() { + mCurTrimNum = 0; + mPathList.clear(); + } + + private void trimOnce() { + if (mCurTrimNum < mSectionList.size()) { + mProcessingDialog.setProgress(0); + mProcessingDialog.setMessage("正在处理第 " + (mCurTrimNum + 1) + "/" + mSectionList.size() + " 段视频 ..."); + mProcessingDialog.show(); + + SectionItem item = mSectionList.get(mCurTrimNum); + if (mShortVideoTrimmer != null) { + mShortVideoTrimmer.destroy(); + } + mShortVideoTrimmer = new PLShortVideoTrimmer(this, mSrcVideoPath, item.mVideoPath); + mShortVideoTrimmer.trim(item.mStartTime, item.mEndTime, PLShortVideoTrimmer.TRIM_MODE.ACCURATE, mSaveListener); + mCurTrimNum += 1; + } else { + mProcessingDialog.dismiss(); + jumpToActivity(); + resetData(); + } + } + + private void noTrimJump() { + mPathList.add(mSrcVideoPath); + jumpToActivity(); + resetData(); + } + + private void jumpToActivity() { + Intent intent = new Intent(this, VideoFrameActivity.class); + intent.putStringArrayListExtra(DATA_EXTRA_PATHS, mPathList); + boolean isJumpedTo = getIntent().getBooleanExtra(DATA_EXTRA_JUMP, false); + if (isJumpedTo) { + setResult(VideoFrameActivity.DIVIDE_REQUEST_CODE, intent); + } else { + startActivity(intent); + } + finish(); + } + + private void addSelectorView() { + mCurSelectorView = new FrameSelectorView(this); + final FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mFrameListParent.getHeight()); + mCurSelectorView.setVisibility(View.INVISIBLE); + mScrollViewParent.addView(mCurSelectorView, layoutParams); + + mCurSelectorView.post(new Runnable() { + @Override + public void run() { + // put mCurSelectorView to the middle of the horizontal + layoutParams.leftMargin = (mScrollViewParent.getWidth() - mCurSelectorView.getWidth()) / 2; + mCurSelectorView.setLayoutParams(layoutParams); + mCurSelectorView.setVisibility(View.VISIBLE); + } + }); + } + + public void addSelectedRect() { + if (mCurSelectorView == null) { + return; + } + + int leftBorder = mCurSelectorView.getBodyLeft(); + int rightBorder = mCurSelectorView.getBodyRight(); + int width = mCurSelectorView.getBodyWidth(); + + boolean outOfLeft = leftBorder <= getHalfGroupWidth() - mScrollView.getScrollX(); + boolean outOfRight = rightBorder >= getHalfGroupWidth() + (getTotalScrollLength() - mScrollView.getScrollX()); + + if (outOfLeft && !outOfRight) { + leftBorder = getHalfGroupWidth() - mScrollView.getScrollX(); + width = rightBorder - leftBorder; + } else if (!outOfLeft && outOfRight) { + width = width - (rightBorder - getHalfGroupWidth() - (getTotalScrollLength() - mScrollView.getScrollX())); + } else if (outOfLeft && outOfRight) { + leftBorder = getHalfGroupWidth() - mScrollView.getScrollX(); + width = getTotalScrollLength(); + } + + if (width <= 0) { + mCurSelectorView.setVisibility(View.GONE); + return; + } + + final View rectView = new View(this); + rectView.setBackground(getResources().getDrawable(R.drawable.frame_selector_rect)); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(width, mFrameListParent.getHeight()); + rectView.setOnTouchListener(new RectViewTouchListener()); + + int leftPosition = leftBorder + mScrollView.getScrollX(); + int rightPosition = leftPosition + width; + + layoutParams.leftMargin = leftPosition; + mFrameListParent.addView(rectView, layoutParams); + + mCurSelectorView.setVisibility(View.GONE); + + SectionItem item = addSection(leftPosition, rightPosition); + rectView.setTag(item); + } + + private SectionItem addSection(int leftPosition, int rightPosition) { + String path = VIDEO_STORAGE_DIR + "pl-trim-" + System.currentTimeMillis() + ".mp4"; + long startTime = getTimeByPosition(leftPosition); + long endTime = getTimeByPosition(rightPosition); + SectionItem sectionItem = new SectionItem(startTime, endTime, path); + mSectionList.add(sectionItem); + return sectionItem; + } + + private long getTimeByPosition(int position) { + position = position - getHalfGroupWidth(); + return (long) ((float) mDurationMs * position / getTotalScrollLength()); + } + + private int getTotalScrollLength() { + return getShowFrameCount() * mFrameWidth; + } + + private int getHalfGroupWidth() { + return mFrameWidth * 3; + } + + private int getScrollLengthByTime(long time) { + return (int) ((float) getTotalScrollLength() * time / mDurationMs); + } + + private void scrollToTime(long time) { + int scrollLength = getScrollLengthByTime(time); + mScrollView.smoothScrollTo(scrollLength, 0); + } + + private int getShowFrameCount() { + return (int) Math.ceil((float) mDurationMs / mShowFrameIntervalMs); + } + + private void startPlayback() { + mPreview.start(); + mPlaybackButton.setImageResource(R.mipmap.btn_pause); + } + + private void pausePlayback() { + mPreview.pause(); + mPlaybackButton.setImageResource(R.mipmap.btn_play); + } + + private boolean isInRangeOfView(View view, MotionEvent ev) { + int[] location = new int[2]; + view.getLocationOnScreen(location); + int x = location[0]; + int y = location[1]; + if (ev.getX() < x || + ev.getX() > (x + view.getWidth()) || + ev.getY() < y || + ev.getY() > (y + view.getHeight())) { + return false; + } + return true; + } + + private void play() { + if (mPreview != null) { + mPreview.seekTo(0); + startPlayback(); + } + } + + private PLVideoSaveListener mSaveListener = new PLVideoSaveListener() { + @Override + public void onSaveVideoSuccess(String destFile) { + mPathList.add(destFile); + runOnUiThread(new Runnable() { + @Override + public void run() { + trimOnce(); + } + }); + } + + @Override + public void onSaveVideoFailed(int errorCode) { + } + + @Override + public void onSaveVideoCanceled() { + } + + @Override + public void onProgressUpdate(final float percentage) { + runOnUiThread(new Runnable() { + @Override + public void run() { + mProcessingDialog.setProgress((int) (100 * percentage)); + } + }); + } + }; + + private class RectViewTouchListener implements View.OnTouchListener { + private View mRectView; + private GestureDetector.SimpleOnGestureListener mSimpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + SectionItem item = (SectionItem) mRectView.getTag(); + mSectionList.remove(item); + mFrameListParent.removeView(mRectView); + return false; + } + }; + private GestureDetector mGestureDetector = new GestureDetector(VideoDivideActivity.this, mSimpleOnGestureListener); + + @Override + public boolean onTouch(View view, MotionEvent event) { + mRectView = view; + if (mGestureDetector.onTouchEvent(event)) { + return true; + } + return true; + } + } + + private class OnTopViewTouchListener implements View.OnTouchListener { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (!isInRangeOfView(mScrollViewParent, event)) { + if (mCurSelectorView != null) { + addSelectedRect(); + mCurSelectorView = null; + } + } + return false; + } + } + + private class OnViewScrollListener implements ObservableHorizontalScrollView.OnScrollListener { + @Override + public void onScrollChanged(ObservableHorizontalScrollView scrollView, final int x, int y, int oldX, int oldY, boolean dragScroll) { + if (dragScroll) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (mPreview.isPlaying()) { + pausePlayback(); + } + int index = x / mFrameWidth; + mPreview.seekTo((int) (index * mShowFrameIntervalMs)); + } + }); + } + } + } + + private class ItemViewHolder extends RecyclerView.ViewHolder { + public ImageView mImageView; + + public ItemViewHolder(View itemView) { + super(itemView); + mImageView = (ImageView) itemView.findViewById(R.id.thumbnail); + } + } + + private class FrameListAdapter extends RecyclerView.Adapter { + + @Override + public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + Context context = parent.getContext(); + LayoutInflater inflater = LayoutInflater.from(context); + + View contactView = inflater.inflate(R.layout.item_devide_frame, parent, false); + ItemViewHolder viewHolder = new ItemViewHolder(contactView); + return viewHolder; + } + + @Override + public void onBindViewHolder(final ItemViewHolder holder, final int position) { + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mFrameWidth, mFrameHeight); + params.width = mFrameWidth; + holder.mImageView.setLayoutParams(params); + + // there are 6 dark frames in begin and end sides + if (position == 0 || + position == 1 || + position == 2 || + position == getShowFrameCount() + 3 || + position == getShowFrameCount() + 4 || + position == getShowFrameCount() + 5) { + return; + } + + long frameTime = (position - 3) * mShowFrameIntervalMs; + new ImageViewTask(holder.mImageView, frameTime, mFrameWidth, mFrameHeight, mMediaFile).execute(); + } + + @Override + public int getItemCount() { + return getShowFrameCount() + 6; + } + + } + + private static class ImageViewTask extends AsyncTask { + private WeakReference mImageViewWeakReference; + private long mFrameTime; + private int mFrameWidth; + private int mFrameHeight; + private PLMediaFile mMediaFile; + + ImageViewTask(ImageView imageView, long frameTime, int frameWidth, int frameHeight, PLMediaFile mediaFile) { + mImageViewWeakReference = new WeakReference<>(imageView); + mFrameTime = frameTime; + mFrameWidth = frameWidth; + mFrameHeight = frameHeight; + mMediaFile = mediaFile; + } + + @Override + protected PLVideoFrame doInBackground(Void... v) { + PLVideoFrame frame = mMediaFile.getVideoFrameByTime(mFrameTime, false, mFrameWidth, mFrameHeight); + return frame; + } + + @Override + protected void onPostExecute(PLVideoFrame frame) { + super.onPostExecute(frame); + ImageView mImageView = mImageViewWeakReference.get(); + if (mImageView == null) { + return; + } + if (frame != null) { + int rotation = frame.getRotation(); + Bitmap bitmap = frame.toBitmap(); + mImageView.setImageBitmap(bitmap); + mImageView.setRotation(rotation); + } + } + } + + private class SectionItem { + long mStartTime; + long mEndTime; + String mVideoPath; + + public SectionItem(long startTime, long endTime, String videoPath) { + mStartTime = startTime; + mEndTime = endTime; + mVideoPath = videoPath; + } + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoEditActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoEditActivity.java index 2cab9c7..3a750b0 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoEditActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoEditActivity.java @@ -1026,7 +1026,7 @@ public void onSurfaceDestroy() { } @Override - public int onDrawFrame(int texId, int texWidth, int texHeight, long timeStampNs, float[] transformMatrix) { + public int onDrawFrame(int texId, int texWidth, int texHeight, long timestampNs, float[] transformMatrix) { if (mCancelSave && mTuSDKManager.getPreviewFilterEngine() == null) { mTuSDKManager.setupPreviewFilterEngine(); mTuSDKManager.getPreviewFilterEngine().onSurfaceCreated(); @@ -1083,8 +1083,8 @@ public void onSurfaceDestroy() { } @Override - public int onDrawFrame(int texId, int texWidth, int texHeight, long timeStampNs, float[] transformMatrix) { - long currentTimeMs = (long) Math.ceil(timeStampNs / 1000000L); + public int onDrawFrame(int texId, int texWidth, int texHeight, long timestampNs, float[] transformMatrix) { + long currentTimeMs = (long) Math.ceil(timestampNs / 1000000L); if (startTimeMs == 0) { startTimeMs = currentTimeMs; } diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoFrameActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoFrameActivity.java new file mode 100644 index 0000000..4186fb2 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoFrameActivity.java @@ -0,0 +1,179 @@ +package com.qiniu.pili.droid.shortvideo.demo.activity; + +import android.app.Activity; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SimpleItemAnimator; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager; +import com.qiniu.pili.droid.shortvideo.PLShortVideoComposer; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.PLVideoSaveListener; +import com.qiniu.pili.droid.shortvideo.demo.R; +import com.qiniu.pili.droid.shortvideo.demo.utils.Config; +import com.qiniu.pili.droid.shortvideo.demo.utils.ToastUtils; +import com.qiniu.pili.droid.shortvideo.demo.view.CustomProgressDialog; +import com.qiniu.pili.droid.shortvideo.demo.view.DragItemAdapter; + +import java.util.ArrayList; + +public class VideoFrameActivity extends Activity { + public static final int TRANSITION_REQUEST_CODE = 1; + public static final int DIVIDE_REQUEST_CODE = 2; + public static final String DATA_EXTRA_PATHS = "paths"; + public static final String DATA_EXTRA_PATH = "path"; + public static final String DATA_EXTRA_JUMP = "jump"; + + private RecyclerView mRecyclerView; + private RecyclerView.LayoutManager mLayoutManager; + private PLShortVideoComposer mShortVideoComposer; + private CustomProgressDialog mProcessingDialog; + private DragItemAdapter mDragItemAdapter; + + private ArrayList mVideoPaths; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.activity_video_frame); + mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); + mLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false); + mRecyclerView.setLayoutManager(mLayoutManager); + ((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false); + + ArrayList arrayList = getIntent().getStringArrayListExtra(DATA_EXTRA_PATHS); + mVideoPaths = (arrayList == null) ? new ArrayList() : arrayList; + + mDragItemAdapter = new DragItemAdapter(mVideoPaths); + mDragItemAdapter.setOnItemMovedListener(new DragItemAdapter.OnItemMovedListener() { + @Override + public void onMoveItem(int fromPosition, int toPosition) { + String movedItem = mVideoPaths.remove(fromPosition); + mVideoPaths.add(toPosition, movedItem); + } + }); + + RecyclerViewDragDropManager dragDropManager = new RecyclerViewDragDropManager(); + dragDropManager.setInitiateOnMove(false); + dragDropManager.setInitiateOnLongPress(true); + + RecyclerView.Adapter adapter = dragDropManager.createWrappedAdapter(mDragItemAdapter); + mRecyclerView.setAdapter(adapter); + dragDropManager.attachRecyclerView(mRecyclerView); + + mShortVideoComposer = new PLShortVideoComposer(this); + mProcessingDialog = new CustomProgressDialog(this); + mProcessingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + mShortVideoComposer.cancelComposeVideos(); + } + }); + } + + @Override + public void onBackPressed() { + showFinishDialog(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // TODO Auto-generated method stub + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == TRANSITION_REQUEST_CODE && data != null) { + String path = data.getStringExtra(DATA_EXTRA_PATH); + if (path != null) { + mVideoPaths.add(path); + } + } else if (requestCode == DIVIDE_REQUEST_CODE && data != null) { + ArrayList appendPaths = data.getStringArrayListExtra(DATA_EXTRA_PATHS); + if (appendPaths != null) { + mVideoPaths.addAll(appendPaths); + } + } + mDragItemAdapter.updatePaths(mVideoPaths); + mDragItemAdapter.notifyDataSetChanged(); + } + + public void onBack(View view) { + showFinishDialog(); + } + + public void onDone(View view) { + PLVideoEncodeSetting setting = new PLVideoEncodeSetting(this); + setting.setEncodingSizeLevel(PLVideoEncodeSetting.VIDEO_ENCODING_SIZE_LEVEL.VIDEO_ENCODING_SIZE_LEVEL_720P_2); + + if (mShortVideoComposer.composeVideos(mVideoPaths, Config.VIDEO_DIVIDE_FILE_PATH, setting, mVideoSaveListener)) { + mProcessingDialog.show(); + } else { + ToastUtils.s(this, "开始拼接失败!"); + } + } + + public void onClickAddVideo(View view) { + Intent intent = new Intent(this, VideoDivideActivity.class); + intent.putExtra(DATA_EXTRA_JUMP, true); + startActivityForResult(intent, DIVIDE_REQUEST_CODE); + } + + public void onClickAddTransition(View view) { + startActivityForResult(new Intent(this, TransitionMakeActivity.class), TRANSITION_REQUEST_CODE); + } + + private void showFinishDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage("确定要放弃剪切的视频吗?") + .setPositiveButton("确定", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + finish(); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + builder.create().show(); + } + + private PLVideoSaveListener mVideoSaveListener = new PLVideoSaveListener() { + @Override + public void onSaveVideoSuccess(final String destFile) { + mProcessingDialog.dismiss(); + PlaybackActivity.start(VideoFrameActivity.this, destFile); + } + + @Override + public void onSaveVideoFailed(int errorCode) { + + } + + @Override + public void onSaveVideoCanceled() { + + } + + @Override + public void onProgressUpdate(final float percentage) { + runOnUiThread(new Runnable() { + @Override + public void run() { + mProcessingDialog.setProgress((int) (100 * percentage)); + } + }); + } + }; +} \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoRecordActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoRecordActivity.java index c92d656..1345548 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoRecordActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoRecordActivity.java @@ -249,7 +249,7 @@ public void onSurfaceDestroy() { } @Override - public int onDrawFrame(int texId, int texWidth, int texHeight, long timeStampNs, float[] transformMatrix) { + public int onDrawFrame(int texId, int texWidth, int texHeight, long timestampNs, float[] transformMatrix) { if (!isTrackerOnSurfaceChangedCalled) { isTrackerOnSurfaceChangedCalled = true; mKiwiTrackWrapper.onSurfaceChanged(surfaceWidth, surfaceHeight, texWidth, texHeight); diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTranscodeActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTranscodeActivity.java index 37996c5..9a63f1f 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTranscodeActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTranscodeActivity.java @@ -158,9 +158,7 @@ private void doTranscode(boolean isReverse) { int transcodingWidth = Integer.parseInt(mTranscodingWidthEditText.getText().toString()); int transcodingHeight = Integer.parseInt(mTranscodingHeightEditText.getText().toString()); - mProcessingDialog.show(); - - mShortVideoTranscoder.transcode( + boolean startResult = mShortVideoTranscoder.transcode( transcodingWidth, transcodingHeight, RecordSettings.ENCODING_BITRATE_LEVEL_ARRAY[transcodingBitrateLevel], RecordSettings.ROTATION_LEVEL_ARRAY[transcodingRotationLevel], @@ -209,6 +207,12 @@ public void run() { }); } }); + + if (startResult) { + mProcessingDialog.show(); + } else { + ToastUtils.s(this, "开始转码失败!"); + } } private void showChooseDialog(final String filePath) { diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTrimActivity.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTrimActivity.java index 5c7f3e1..558f541 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTrimActivity.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/activity/VideoTrimActivity.java @@ -38,8 +38,6 @@ import java.util.Locale; import java.util.concurrent.TimeUnit; -import static com.qiniu.pili.droid.shortvideo.PLErrorCode.ERROR_MULTI_CODEC_WRONG; - public class VideoTrimActivity extends Activity { private static final String TAG = "VideoTrimActivity"; diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition0.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition0.java new file mode 100644 index 0000000..e573906 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition0.java @@ -0,0 +1,57 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLFadeTransition; +import com.qiniu.pili.droid.shortvideo.PLPositionTransition; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class Transition0 extends TransitionBase { + public Transition0(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + super(viewGroup, setting); + } + + @Override + protected void initPosAndTrans() { + //you should init positions and transitions in post runnable , because the view has been layout at that moment. + mTitle.post(new Runnable() { + @Override + public void run() { + initPosition(); + initTransitions(); + } + }); + } + + private void initTransitions() { + PLFadeTransition fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mTitle, fadeTransition); + PLPositionTransition positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mTitle.getX(), (int) mTitle.getY(), (int) mTitle.getX(), (int) mTitle.getY() - mTitle.getHeight()); + mTransitionMaker.addTransition(mTitle, positionTransition); + + mTransitionMaker.play(); + setViewsVisible(View.VISIBLE); + } + + private void initPosition() { + int titleX = mWidth / 2 - mTitle.getWidth() / 2; + int titleY = mHeight / 2 + mTitle.getHeight() / 2; + mTitle.setTranslationX(titleX); + mTitle.setTranslationY(titleY); + } + + @Override + protected void initViews() { + mTitle = new TransitionTextView(mContext); + mTitle.setText("七月与安生"); + mTitle.setPadding(0, 0, 0, 0); + mTitle.setTextColor(Color.WHITE); + mTitle.setTextSize(26); + + addViews(); + setViewsVisible(View.INVISIBLE); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition1.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition1.java new file mode 100644 index 0000000..f7bd0c4 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition1.java @@ -0,0 +1,79 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLFadeTransition; +import com.qiniu.pili.droid.shortvideo.PLPositionTransition; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class Transition1 extends TransitionBase { + public Transition1(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + super(viewGroup, setting); + } + + @Override + public void init() { + mTransitionMaker.setDuration(DURATION); + mTransitionMaker.setBackgroundColor(Color.BLACK); + + initViews(); + initPosAndTrans(); + } + + @Override + public void updateTransitions() { + mTransitionMaker.removeAllResource(); + addViews(); + initPosAndTrans(); + } + + @Override + protected void initViews() { + mTitle = new TransitionTextView(mContext); + mTitle.setText("CHAPTER"); + mTitle.setPadding(0, 0, 0, 0); + mTitle.setTextColor(Color.parseColor("#FFCC99")); + mTitle.setTextSize(14); + + mSubtitle = new TransitionTextView(mContext); + mSubtitle.setText("第一章 七年"); + mSubtitle.setPadding(0, 0, 0, 0); + mSubtitle.setTextColor(Color.WHITE); + mSubtitle.setTextSize(20); + + addViews(); + setViewsVisible(View.INVISIBLE); + } + + protected void initPosAndTrans() { + //you should init positions and transitions in post runnable , because the view has been layout at that moment. + mSubtitle.post(new Runnable() { + @Override + public void run() { + initPosition(); + initTransitions(); + } + }); + } + + private void initTransitions() { + PLFadeTransition fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mTitle, fadeTransition); + PLPositionTransition positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mSubtitle.getX(), (int) mSubtitle.getY(), (int) mSubtitle.getX() - mSubtitle.getWidth(), (int) mSubtitle.getY()); + mTransitionMaker.addTransition(mSubtitle, positionTransition); + + mTransitionMaker.play(); + setViewsVisible(View.VISIBLE); + } + + private void initPosition() { + mTitle.setTranslationX(mWidth - mTitle.getWidth()); + mTitle.setTranslationY(mHeight / 2 - mTitle.getHeight()); + + mSubtitle.setTranslationX(mWidth); + mSubtitle.setTranslationY(mTitle.getY() + mTitle.getHeight()); + } +} \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition2.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition2.java new file mode 100644 index 0000000..4ef08d1 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition2.java @@ -0,0 +1,78 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLFadeTransition; +import com.qiniu.pili.droid.shortvideo.PLImageView; +import com.qiniu.pili.droid.shortvideo.PLPositionTransition; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.demo.R; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class Transition2 extends TransitionBase { + private PLImageView mImageView; + + public Transition2(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + super(viewGroup, setting); + } + + @Override + protected void initPosAndTrans() { + //you should init positions and transitions in post runnable , because the view has been layout at that moment. + mImageView.post(new Runnable() { + @Override + public void run() { + initPosition(); + initTransitions(); + } + }); + } + + @Override + protected void initViews() { + mTitle = new TransitionTextView(mContext); + mTitle.setText("第二章 暖暖"); + mTitle.setPadding(0, 0, 0, 0); + mTitle.setTextColor(Color.WHITE); + mTitle.setTextSize(22); + + mImageView = new PLImageView(mContext); + mImageView.setImageDrawable(mContext.getResources().getDrawable(R.drawable.pink_line)); + + addViews(); + setViewsVisible(View.INVISIBLE); + } + + private void initPosition() { + int titleY = mHeight / 2 - mTitle.getHeight(); + mTitle.setTranslationX(0); + mTitle.setTranslationY(titleY); + + mImageView.setTranslationY(mHeight / 2 - mTitle.getHeight() - mImageView.getHeight()); + mImageView.setTranslationX(0); + } + + private void initTransitions() { + PLFadeTransition fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mImageView, fadeTransition); + PLPositionTransition positionTransition = new PLPositionTransition(0, DURATION / 2, -mTitle.getWidth(), (int) mTitle.getY(), (int) mTitle.getX(), (int) mTitle.getY()); + mTransitionMaker.addTransition(mTitle, positionTransition); + + mTransitionMaker.play(); + setViewsVisible(View.VISIBLE); + } + + @Override + protected void addViews() { + super.addViews(); + mTransitionMaker.addImage(mImageView); + } + + @Override + protected void setViewsVisible(int visible) { + super.setViewsVisible(visible); + mImageView.setVisibility(visible); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition3.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition3.java new file mode 100644 index 0000000..6c38207 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition3.java @@ -0,0 +1,88 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLFadeTransition; +import com.qiniu.pili.droid.shortvideo.PLImageView; +import com.qiniu.pili.droid.shortvideo.PLPositionTransition; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.demo.R; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class Transition3 extends TransitionBase { + private static final int MOVE_DISTANCE = 100; + + private static final String TEXT_DISPLAY = "村上春树1949年1月12日出生在日本京都市伏见区,为国语教师村上千秋、村上美幸夫妇的长子。出生不久,家迁至兵库县西宫市夙川。村上春树1949年1月12日出生在日本京都市伏见区,为国语教师村上千秋、村上美幸夫妇的长子。出生不久,家迁至兵库县西宫市夙川。"; + + private PLImageView mImageView; + + public Transition3(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + super(viewGroup, setting); + } + + @Override + protected void initPosAndTrans() { + //you should init positions and transitions in post runnable , because the view has been layout at that moment. + mImageView.post(new Runnable() { + @Override + public void run() { + initPosition(); + initTransitions(); + } + }); + } + + @Override + protected void initViews() { + mTitle = new TransitionTextView(mContext); + mTitle.setText(TEXT_DISPLAY); + mTitle.setPadding(0, 0, 0, 0); + mTitle.setTextColor(Color.parseColor("#339900")); + mTitle.setTextSize(16); + + mImageView = new PLImageView(mContext); + mImageView.setImageDrawable(mContext.getResources().getDrawable(R.drawable.green_quot)); + + addViews(); + setViewsVisible(View.INVISIBLE); + } + + private void initTransitions() { + PLPositionTransition positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mTitle.getX(), (int) mTitle.getY(), (int) mTitle.getX(), (int) mTitle.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mTitle, positionTransition); + PLFadeTransition fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mTitle, fadeTransition); + + positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mImageView.getX(), (int) mImageView.getY(), (int) mImageView.getX(), (int) mImageView.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mImageView, positionTransition); + fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mImageView, fadeTransition); + + mTransitionMaker.play(); + setViewsVisible(View.VISIBLE); + } + + private void initPosition() { + int titleY = mHeight / 2 - mTitle.getHeight() / 2 + MOVE_DISTANCE; + mTitle.setTranslationX(0); + mTitle.setTranslationY(titleY); + + int imageY = titleY - mImageView.getHeight(); + mImageView.setTranslationY(imageY); + mImageView.setTranslationX(0); + } + + @Override + protected void addViews() { + super.addViews(); + mTransitionMaker.addImage(mImageView); + } + + @Override + protected void setViewsVisible(int visible) { + super.setViewsVisible(visible); + mImageView.setVisibility(visible); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition4.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition4.java new file mode 100644 index 0000000..889efc7 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition4.java @@ -0,0 +1,75 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLFadeTransition; +import com.qiniu.pili.droid.shortvideo.PLPositionTransition; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class Transition4 extends TransitionBase { + private static final int MOVE_DISTANCE = 100; + + public Transition4(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + super(viewGroup, setting); + } + + @Override + protected void initPosAndTrans() { + //you should init positions and transitions in post runnable , because the view has been layout at that moment. + mSubtitle.post(new Runnable() { + @Override + public void run() { + initPosition(); + initTransitions(); + } + }); + } + + private void initTransitions() { + PLFadeTransition fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mTitle, fadeTransition); + PLPositionTransition positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mTitle.getX(), (int) mTitle.getY(), (int) mTitle.getX(), (int) mTitle.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mTitle, positionTransition); + + fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mSubtitle, fadeTransition); + positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mSubtitle.getX(), (int) mSubtitle.getY(), (int) mSubtitle.getX(), (int) mSubtitle.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mSubtitle, positionTransition); + + mTransitionMaker.play(); + setViewsVisible(View.VISIBLE); + } + + private void initPosition() { + int titleX = mWidth / 2 - mTitle.getWidth() / 2; + int titleY = mHeight / 2 - mTitle.getHeight() + MOVE_DISTANCE; + mTitle.setTranslationX(titleX); + mTitle.setTranslationY(titleY); + + int subtitleX = mWidth / 2 - mSubtitle.getWidth() / 2; + int subtitleY = titleY + mTitle.getHeight(); + mSubtitle.setTranslationX(subtitleX); + mSubtitle.setTranslationY(subtitleY); + } + + @Override + protected void initViews() { + mTitle = new TransitionTextView(mContext); + mTitle.setText("挪威的森林"); + mTitle.setPadding(0, 0, 0, 0); + mTitle.setTextColor(Color.WHITE); + mTitle.setTextSize(22); + + mSubtitle = new TransitionTextView(mContext); + mSubtitle.setText("- 村上春树 -"); + mSubtitle.setPadding(0, 0, 0, 0); + mSubtitle.setTextColor(Color.parseColor("#eed2b9")); + mSubtitle.setTextSize(15); + + addViews(); + setViewsVisible(View.INVISIBLE); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition5.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition5.java new file mode 100644 index 0000000..ee970dc --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/Transition5.java @@ -0,0 +1,130 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.graphics.Color; +import android.view.View; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLFadeTransition; +import com.qiniu.pili.droid.shortvideo.PLPositionTransition; +import com.qiniu.pili.droid.shortvideo.PLTextView; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class Transition5 extends TransitionBase { + private PLTextView mTitleTip; + private PLTextView mSubtitleTip; + + private static final int MOVE_DISTANCE = 100; + + public Transition5(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + super(viewGroup, setting); + } + + @Override + protected void initPosAndTrans() { + //you should init positions and transitions in post runnable , because the view has been layout at that moment. + mSubtitle.post(new Runnable() { + @Override + public void run() { + initPosition(); + initTransitions(); + } + }); + } + + private void initTransitions() { + //title transitions + PLFadeTransition fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mTitle, fadeTransition); + PLPositionTransition positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mTitle.getX(), (int) mTitle.getY(), (int) mTitle.getX(), (int) mTitle.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mTitle, positionTransition); + + //subtitle transitions + fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mSubtitle, fadeTransition); + positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mSubtitle.getX(), (int) mSubtitle.getY(), (int) mSubtitle.getX(), (int) mSubtitle.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mSubtitle, positionTransition); + + //title tip transitions + fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mTitleTip, fadeTransition); + positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mTitleTip.getX(), (int) mTitleTip.getY(), (int) mTitleTip.getX(), (int) mTitleTip.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mTitleTip, positionTransition); + + //subtitle tip transitions + fadeTransition = new PLFadeTransition(0, DURATION / 2, 0, 1); + mTransitionMaker.addTransition(mSubtitleTip, fadeTransition); + positionTransition = new PLPositionTransition(0, DURATION / 2, (int) mSubtitleTip.getX(), (int) mSubtitleTip.getY(), (int) mSubtitleTip.getX(), (int) mSubtitleTip.getY() - MOVE_DISTANCE); + mTransitionMaker.addTransition(mSubtitleTip, positionTransition); + + mTransitionMaker.play(); + setViewsVisible(View.VISIBLE); + } + + private void initPosition() { + int titleX = mWidth / 2 - mTitle.getWidth() / 2; + int titleY = mHeight / 2 - mTitle.getHeight() + MOVE_DISTANCE; + mTitle.setTranslationX(titleX); + mTitle.setTranslationY(titleY); + + int titleTipX = mWidth / 2 - mTitleTip.getWidth() / 2; + int titleTipY = titleY - mTitleTip.getHeight(); + mTitleTip.setTranslationX(titleTipX); + mTitleTip.setTranslationY(titleTipY); + + int subtitleTipX = mWidth / 2 - mSubtitleTip.getWidth() / 2; + int subtitleTipY = mHeight / 2 + MOVE_DISTANCE; + mSubtitleTip.setTranslationX(subtitleTipX); + mSubtitleTip.setTranslationY(subtitleTipY); + + int subtitleX = mWidth / 2 - mSubtitle.getWidth() / 2; + int subtitleY = subtitleTipY + mSubtitleTip.getHeight(); + mSubtitle.setTranslationX(subtitleX); + mSubtitle.setTranslationY(subtitleY); + } + + + @Override + protected void initViews() { + mTitle = new TransitionTextView(mContext); + mTitle.setText("七牛"); + mTitle.setPadding(0, 0, 0, 0); + mTitle.setTextColor(Color.parseColor("#FFCC99")); + mTitle.setTextSize(16); + + mTitleTip = new TransitionTextView(mContext); + mTitleTip.setText("DIRECTOR"); + mTitleTip.setPadding(0, 0, 0, 0); + mTitleTip.setTextColor(Color.parseColor("#FFFFFF")); + mTitleTip.setTextSize(16); + + mSubtitleTip = new TransitionTextView(mContext); + mSubtitleTip.setText("DATE&LOCATION"); + mSubtitleTip.setPadding(0, 0, 0, 0); + mSubtitleTip.setTextColor(Color.parseColor("#FFFFFF")); + mSubtitleTip.setTextSize(16); + + mSubtitle = new TransitionTextView(mContext); + mSubtitle.setText("2018.1.1 上海"); + mSubtitle.setPadding(0, 0, 0, 0); + mSubtitle.setTextColor(Color.parseColor("#FFCC99")); + mSubtitle.setTextSize(16); + + addViews(); + setViewsVisible(View.INVISIBLE); + } + + @Override + protected void addViews() { + super.addViews(); + mTransitionMaker.addText(mTitleTip); + mTransitionMaker.addText(mSubtitleTip); + } + + @Override + protected void setViewsVisible(int visible) { + super.setViewsVisible(visible); + mTitleTip.setVisibility(visible); + mSubtitleTip.setVisibility(visible); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/TransitionBase.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/TransitionBase.java new file mode 100644 index 0000000..29e0df9 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/transition/TransitionBase.java @@ -0,0 +1,102 @@ +package com.qiniu.pili.droid.shortvideo.demo.transition; + +import android.content.Context; +import android.graphics.Color; +import android.view.ViewGroup; + +import com.qiniu.pili.droid.shortvideo.PLTransitionMaker; +import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting; +import com.qiniu.pili.droid.shortvideo.PLVideoSaveListener; +import com.qiniu.pili.droid.shortvideo.demo.view.TransitionTextView; + +public class TransitionBase { + protected static final int DURATION = 2500; + + private ViewGroup mViewGroup; + + protected PLTransitionMaker mTransitionMaker; + protected Context mContext; + protected TransitionTextView mTitle; + protected TransitionTextView mSubtitle; + protected int mWidth; + protected int mHeight; + + public TransitionBase(ViewGroup viewGroup, PLVideoEncodeSetting setting) { + mViewGroup = viewGroup; + mContext = viewGroup.getContext(); + mWidth = mViewGroup.getWidth(); + mHeight = mViewGroup.getHeight(); + mTransitionMaker = new PLTransitionMaker(mViewGroup, setting); + init(); + } + + public TransitionTextView getTitle() { + return mTitle; + } + + public TransitionTextView getSubtitle() { + return mSubtitle; + } + + public void init() { + mTransitionMaker.setDuration(DURATION); + mTransitionMaker.setBackgroundColor(Color.BLACK); + + initViews(); + initPosAndTrans(); + } + + public void save(String dstFilePath, PLVideoSaveListener saveListener) { + mTransitionMaker.save(dstFilePath, saveListener); + } + + public void setVisibility(int visibility) { + mViewGroup.setVisibility(visibility); + } + + public void play() { + mTransitionMaker.play(); + } + + public void stop() { + mTransitionMaker.stop(); + } + + public void destroy() { + mTransitionMaker.destroy(); + } + + public void cancelSave() { + mTransitionMaker.cancelSave(); + } + + public void updateTransitions() { + mTransitionMaker.removeAllResource(); + addViews(); + initPosAndTrans(); + } + + protected void initViews() { + } + + protected void initPosAndTrans() { + } + + protected void addViews() { + if (mTitle != null) { + mTransitionMaker.addText(mTitle); + } + if (mSubtitle != null) { + mTransitionMaker.addText(mSubtitle); + } + } + + protected void setViewsVisible(int visible) { + if (mTitle != null) { + mTitle.setVisibility(visible); + } + if (mSubtitle != null) { + mSubtitle.setVisibility(visible); + } + } +} \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/tusdk/TuSDKManager.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/tusdk/TuSDKManager.java index e208537..6eba1c2 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/tusdk/TuSDKManager.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/tusdk/TuSDKManager.java @@ -124,7 +124,7 @@ private TuSDKFilterEngine createFilterEngine() { // 设置输入的图片朝向 如果输入的图片不是原始朝向 该选项必须配置 filterEngine.setInputImageOrientation(ImageOrientation.DownMirrored); // 设置是否开启动态贴纸功能 - filterEngine.setEnableLiveSticker(true); + filterEngine.setEnableLiveSticker(false); return filterEngine; } diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/utils/Config.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/utils/Config.java index b4ddda0..4f0baea 100644 --- a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/utils/Config.java +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/utils/Config.java @@ -19,4 +19,5 @@ public class Config { public static final String SCREEN_RECORD_FILE_PATH = VIDEO_STORAGE_DIR + "screen_record.mp4"; public static final String COMPOSE_FILE_PATH = VIDEO_STORAGE_DIR + "composed.mp4"; public static final String IMAGE_COMPOSE_FILE_PATH = VIDEO_STORAGE_DIR + "image_composed.mp4"; + public static final String VIDEO_DIVIDE_FILE_PATH = VIDEO_STORAGE_DIR + "divide_composed.mp4"; } \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/DragItemAdapter.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/DragItemAdapter.java new file mode 100644 index 0000000..1348dbf --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/DragItemAdapter.java @@ -0,0 +1,142 @@ +package com.qiniu.pili.droid.shortvideo.demo.view; + +import android.graphics.Bitmap; +import android.media.ThumbnailUtils; +import android.provider.MediaStore; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter; +import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange; +import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableItemViewHolder; +import com.qiniu.pili.droid.shortvideo.demo.R; + +import java.util.ArrayList; +import java.util.List; + +import static android.media.ThumbnailUtils.OPTIONS_RECYCLE_INPUT; + +public class DragItemAdapter extends RecyclerView.Adapter + implements DraggableItemAdapter { + + public interface OnItemMovedListener { + void onMoveItem(int fromPosition, int toPosition); + } + + private List mItemList; + private OnItemMovedListener mOnItemMovedListener; + + public DragItemAdapter(ArrayList paths) { + setHasStableIds(true); + + mItemList = new ArrayList<>(); + for (int i = 0; i < paths.size(); i++) { + mItemList.add(new FrameItem(i, paths.get(i))); + } + } + + public void updatePaths(ArrayList paths) { + mItemList.clear(); + for (int i = 0; i < paths.size(); i++) { + mItemList.add(new FrameItem(i, paths.get(i))); + } + } + + public void setOnItemMovedListener(OnItemMovedListener onItemMovedListener) { + mOnItemMovedListener = onItemMovedListener; + } + + @Override + public FrameItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + final View v = inflater.inflate(R.layout.item_image, parent, false); + return new FrameItemViewHolder(v); + } + + @Override + public void onBindViewHolder(final FrameItemViewHolder holder, int position) { + FrameItem item = mItemList.get(position); + final String filepath = item.mPath; + + Bitmap bitmap = (item.mBitmap == null) ? getVideoThumbnail(filepath) : item.mBitmap; + if (bitmap != null) { + holder.mImageView.setImageBitmap(bitmap); + } + item.mBitmap = bitmap; + } + + private Bitmap getVideoThumbnail(String videoPath) { + Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.FULL_SCREEN_KIND); + if (bitmap != null) { + return ThumbnailUtils.extractThumbnail(bitmap, 250, 250, OPTIONS_RECYCLE_INPUT); + } + return null; + } + + public class FrameItemViewHolder extends AbstractDraggableItemViewHolder { + ImageView mImageView; + + public FrameItemViewHolder(View v) { + super(v); + mImageView = (ImageView) v.findViewById(R.id.ImageThumbnail); + } + } + + @Override + public long getItemId(int position) { + // requires static value, it means need to keep the same value + // even if the item position has been changed. + return mItemList.get(position).mID; + } + + + @Override + public int getItemCount() { + return mItemList.size(); + } + + @Override + public boolean onCheckCanStartDrag(FrameItemViewHolder holder, int position, int x, int y) { + View dragHandle = holder.mImageView; + int handleWidth = dragHandle.getWidth(); + int handleHeight = dragHandle.getHeight(); + int handleLeft = dragHandle.getLeft(); + int handleTop = dragHandle.getTop(); + + return (x >= handleLeft) && (x < handleLeft + handleWidth) && + (y >= handleTop) && (y < handleTop + handleHeight); + } + + @Override + public ItemDraggableRange onGetItemDraggableRange(FrameItemViewHolder holder, int position) { + return null; + } + + @Override + public void onMoveItem(int fromPosition, int toPosition) { + FrameItem movedItem = mItemList.remove(fromPosition); + mItemList.add(toPosition, movedItem); + if (mOnItemMovedListener != null) { + mOnItemMovedListener.onMoveItem(fromPosition, toPosition); + } + } + + @Override + public boolean onCheckCanDrop(int draggingPosition, int dropPosition) { + return true; + } + + static class FrameItem { + final long mID; + final String mPath; + Bitmap mBitmap; + + public FrameItem(long id, String text) { + this.mID = id; + this.mPath = text; + } + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/FrameSelectorView.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/FrameSelectorView.java new file mode 100644 index 0000000..62319f4 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/FrameSelectorView.java @@ -0,0 +1,131 @@ +package com.qiniu.pili.droid.shortvideo.demo.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.qiniu.pili.droid.shortvideo.demo.R; + +public class FrameSelectorView extends RelativeLayout { + private ImageView mHandlerLeft; + private ImageView mHandlerRight; + private View mHandlerBody; + private FrameLayout.LayoutParams mGroupLayoutParam; + + private float mOriginX; + private int mOriginWidth; + private ViewGroup.LayoutParams mOriginParam; + private int mOriginLeftMargin; + + private boolean mIsTouching; + + public FrameSelectorView(Context context) { + this(context, null); + } + + public FrameSelectorView(Context context, AttributeSet attrs) { + super(context, attrs); + View view = LayoutInflater.from(context).inflate(R.layout.frame_selector_view, this); + + mHandlerLeft = (ImageView) view.findViewById(R.id.handler_left); + mHandlerRight = (ImageView) view.findViewById(R.id.handler_right); + mHandlerBody = view.findViewById(R.id.handler_body); + + mHandlerLeft.setOnTouchListener(new HandlerLeftTouchListener()); + mHandlerRight.setOnTouchListener(new HandlerRightTouchListener()); + mHandlerBody.setOnTouchListener(new HandlerBodyTouchListener()); + + post(new Runnable() { + @Override + public void run() { + mGroupLayoutParam = (FrameLayout.LayoutParams) getLayoutParams(); + } + }); + } + + private class HandlerLeftTouchListener implements OnTouchListener { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mIsTouching) { + return false; + } + mOriginX = event.getRawX(); + mOriginWidth = mHandlerBody.getWidth(); + mOriginParam = mHandlerBody.getLayoutParams(); + mOriginLeftMargin = mGroupLayoutParam.leftMargin; + mIsTouching = true; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + int delta = (int) (event.getRawX() - mOriginX); + mOriginParam.width = mOriginWidth - delta; + mHandlerBody.setLayoutParams(mOriginParam); + mGroupLayoutParam.leftMargin = mOriginLeftMargin + delta; + setLayoutParams(mGroupLayoutParam); + } else if (event.getAction() == MotionEvent.ACTION_UP) { + mIsTouching = false; + } + return true; + } + } + + private class HandlerRightTouchListener implements OnTouchListener { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mIsTouching) { + return false; + } + mOriginX = event.getRawX(); + mOriginWidth = mHandlerBody.getWidth(); + mOriginParam = mHandlerBody.getLayoutParams(); + mIsTouching = true; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + int delta = (int) (event.getRawX() - mOriginX); + mOriginParam.width = mOriginWidth + delta; + mHandlerBody.setLayoutParams(mOriginParam); + } else if (event.getAction() == MotionEvent.ACTION_UP) { + mIsTouching = false; + } + return true; + } + } + + private class HandlerBodyTouchListener implements OnTouchListener { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mIsTouching) { + return false; + } + mOriginX = event.getRawX(); + mOriginLeftMargin = mGroupLayoutParam.leftMargin; + mIsTouching = true; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + int delta = (int) (event.getRawX() - mOriginX); + mGroupLayoutParam.leftMargin = mOriginLeftMargin + delta; + setLayoutParams(mGroupLayoutParam); + } else if (event.getAction() == MotionEvent.ACTION_UP) { + mIsTouching = false; + } + return true; + } + } + + public int getBodyLeft() { + return mGroupLayoutParam.leftMargin + mHandlerLeft.getWidth(); + } + + public int getBodyWidth() { + return mHandlerBody.getWidth(); + } + + public int getBodyRight() { + return getBodyLeft() + mHandlerBody.getWidth(); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/ObservableHorizontalScrollView.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/ObservableHorizontalScrollView.java new file mode 100644 index 0000000..e233aa7 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/ObservableHorizontalScrollView.java @@ -0,0 +1,79 @@ +package com.qiniu.pili.droid.shortvideo.demo.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.HorizontalScrollView; + +public class ObservableHorizontalScrollView extends HorizontalScrollView { + public interface OnScrollListener { + void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY, boolean dragScroll); + } + + private boolean mIsScrolling; + private boolean mIsTouching; + private boolean mIsDragScroll; + private Runnable mScrollingRunnable; + private OnScrollListener mOnScrollListener; + + public ObservableHorizontalScrollView(Context context) { + this(context, null, 0); + } + + public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + int action = ev.getAction(); + + if (action == MotionEvent.ACTION_MOVE) { + mIsTouching = true; + mIsScrolling = true; + mIsDragScroll = true; + } else if (action == MotionEvent.ACTION_UP) { + mIsTouching = false; + } + + return super.onTouchEvent(ev); + } + + @Override + protected void onScrollChanged(int x, int y, int oldX, int oldY) { + super.onScrollChanged(x, y, oldX, oldY); + + if (Math.abs(oldX - x) > 0) { + if (mScrollingRunnable != null) { + removeCallbacks(mScrollingRunnable); + } + + mScrollingRunnable = new Runnable() { + public void run() { + if (mIsScrolling && !mIsTouching) { + if (mOnScrollListener != null) { + mIsDragScroll = false; + } + } + mIsScrolling = false; + mScrollingRunnable = null; + } + }; + postDelayed(mScrollingRunnable, 200); + } else { + mIsDragScroll = false; + } + + if (mOnScrollListener != null) { + mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY, mIsDragScroll); + } + } + + public void setOnScrollListener(OnScrollListener onScrollListener) { + this.mOnScrollListener = onScrollListener; + } +} \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/TransitionEditView.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/TransitionEditView.java new file mode 100644 index 0000000..35524b0 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/TransitionEditView.java @@ -0,0 +1,241 @@ +package com.qiniu.pili.droid.shortvideo.demo.view; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.support.annotation.Nullable; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.NumberPicker; +import android.widget.TextView; + +import com.qiniu.pili.droid.shortvideo.demo.R; +import com.qiniu.pili.droid.shortvideo.demo.transition.TransitionBase; +import com.qiniu.pili.droid.shortvideo.demo.utils.ToastUtils; + +public class TransitionEditView extends LinearLayout { + public static final String[] TEXT_COLOR_TIPS_ARRAY = { + "#FFFFFF", "#FF3D49", "#FFEE00", "#578BFF", "#00C6FF", "#EACFD4", "#F8EADA", "#CEFFC6", "#C3CADA", "#000000" + }; + public static final String[] TEXT_SIZE_TIPS_ARRAY = { + "46", "50", "54", "58", "62", "66", "70", "74", "78", "82", "86", "90" + }; + public static final String[] TEXT_TYPEFFACE_TIPS_ARRAY = { + "Sans_Serif", "Default_Bold", "zcool-gdh", "HappyZcool-2016" + }; + + private TransitionBase mTransition; + private Button mBackBtn; + private EditText mTitleEditText; + private EditText mSubtitleEditText; + + private TransitionTextView mTransitionTitle; + private TransitionTextView mTransitionSubtitle; + private EditText mCurFocusText; + private NumberPicker mNumberPicker; + private ViewGroup mNumberPickerGroup; + private TextView mConfirmText; + + private Typeface[] mTypefaces; + + private ViewGroup mColorGroup; + private ViewGroup mSizeGroup; + private ViewGroup mTypefaceGroup; + + private Context mContext; + + public TransitionEditView(Context context) { + this(context, null); + } + + public TransitionEditView(final Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + mContext = context; + View view = LayoutInflater.from(context).inflate(R.layout.transition_edit_view, this); + mBackBtn = (Button) view.findViewById(R.id.back_button); + mTitleEditText = (EditText) view.findViewById(R.id.title_edit_text); + mSubtitleEditText = (EditText) view.findViewById(R.id.subtitle_edit_text); + mNumberPicker = (NumberPicker) view.findViewById(R.id.number_picker); + mColorGroup = (ViewGroup) view.findViewById(R.id.color_group); + mSizeGroup = (ViewGroup) view.findViewById(R.id.size_group); + mTypefaceGroup = (ViewGroup) view.findViewById(R.id.typeface_group); + mNumberPickerGroup = (ViewGroup) view.findViewById(R.id.number_picker_group); + mConfirmText = (TextView) view.findViewById(R.id.text_confirm); + + mConfirmText.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mNumberPickerGroup.setVisibility(GONE); + + if (mCurFocusText == mTitleEditText && null != mTransitionTitle) { + cloneEditText(mTransitionTitle, mCurFocusText); + } + if (mCurFocusText == mSubtitleEditText && null != mTransitionSubtitle) { + cloneEditText(mTransitionSubtitle, mCurFocusText); + } + + mTransition.updateTransitions(); + } + }); + + mColorGroup.setOnClickListener(mOnClickListener); + mSizeGroup.setOnClickListener(mOnClickListener); + mTypefaceGroup.setOnClickListener(mOnClickListener); + mTitleEditText.setOnFocusChangeListener(mOnFocusChangeListener); + mSubtitleEditText.setOnFocusChangeListener(mOnFocusChangeListener); + + mBackBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + hideSoftInput(); + setVisibility(GONE); + } + }); + + initTypeFaces(); + } + + private void initTypeFaces() { + mTypefaces = new Typeface[4]; + mTypefaces[0] = Typeface.SANS_SERIF; + mTypefaces[1] = Typeface.DEFAULT_BOLD; + mTypefaces[2] = Typeface.createFromAsset(mContext.getAssets(), "fonts/zcool-gdh.ttf"); + mTypefaces[3] = Typeface.createFromAsset(mContext.getAssets(), "fonts/HappyZcool-2016.ttf"); + } + + private OnClickListener mOnClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + showNumberPicker(v); + } + }; + + private void hideSoftInput() { + InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.hideSoftInputFromWindow(mCurFocusText.getWindowToken(), 0); + } + } + + private void showNumberPicker(final View view) { + if (null == mCurFocusText) { + ToastUtils.s(mContext, "请先选中需要修改的文字"); + return; + } + + hideSoftInput(); + + mNumberPickerGroup.setVisibility(VISIBLE); + String[] array; + switch (view.getId()) { + case R.id.color_group: + array = TEXT_COLOR_TIPS_ARRAY; + break; + case R.id.size_group: + array = TEXT_SIZE_TIPS_ARRAY; + break; + default: + array = TEXT_TYPEFFACE_TIPS_ARRAY; + break; + } + mNumberPicker.setDisplayedValues(null); + mNumberPicker.setMinValue(0); + mNumberPicker.setMaxValue(array.length - 1); + mNumberPicker.setDisplayedValues(array); + mNumberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + switch (view.getId()) { + case R.id.color_group: + mCurFocusText.setTextColor(Color.parseColor(TEXT_COLOR_TIPS_ARRAY[newVal])); + break; + case R.id.size_group: + mCurFocusText.setTextSize(TypedValue.COMPLEX_UNIT_PX, Integer.parseInt(TEXT_SIZE_TIPS_ARRAY[newVal])); + break; + default: + mCurFocusText.setTypeface(mTypefaces[newVal]); + break; + } + } + }); + } + + private OnFocusChangeListener mOnFocusChangeListener = new OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + mCurFocusText = (EditText) v; + } + } + }; + + public void setTransition(TransitionBase transition) { + mTransition = transition; + mTransitionTitle = mTransition.getTitle(); + mTransitionSubtitle = mTransition.getSubtitle(); + + mTitleEditText.setVisibility(GONE); + mSubtitleEditText.setVisibility(GONE); + + if (mTransitionTitle != null) { + mTitleEditText.setVisibility(VISIBLE); + mCurFocusText = mTitleEditText; + cloneEditText(mTitleEditText, mTransitionTitle); + mTitleEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + if (getVisibility() == View.VISIBLE) { + cloneEditText(mTransitionTitle, mTitleEditText); + mTransition.updateTransitions(); + } + } + }); + } + + if (mTransitionSubtitle != null) { + mSubtitleEditText.setVisibility(VISIBLE); + cloneEditText(mSubtitleEditText, mTransitionSubtitle); + mSubtitleEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + if (getVisibility() == View.VISIBLE) { + cloneEditText(mTransitionSubtitle, mSubtitleEditText); + mTransition.updateTransitions(); + } + } + }); + } + } + + private void cloneEditText(EditText dstText, EditText srcText) { + dstText.setText(srcText.getText()); + dstText.setTextColor(srcText.getTextColors()); + dstText.setTypeface(srcText.getTypeface()); + dstText.setTextSize(TypedValue.COMPLEX_UNIT_PX, srcText.getTextSize()); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/TransitionTextView.java b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/TransitionTextView.java new file mode 100644 index 0000000..3a42341 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/java/com/qiniu/pili/droid/shortvideo/demo/view/TransitionTextView.java @@ -0,0 +1,20 @@ +package com.qiniu.pili.droid.shortvideo.demo.view; + +import android.content.Context; +import android.util.AttributeSet; + +import com.qiniu.pili.droid.shortvideo.PLTextView; + +public class TransitionTextView extends PLTextView{ + public TransitionTextView(Context context) { + this(context, null); + } + + public TransitionTextView(Context context, AttributeSet attrs) { + super(context, attrs); + setFocusable(false); + setFocusableInTouchMode(false); + setClickable(false); + setPadding(0, 0, 0, 0); + } +} diff --git a/PLDroidShortVideoDemo/app/src/main/jniLibs/armeabi-v7a/libpldroid_beauty.so b/PLDroidShortVideoDemo/app/src/main/jniLibs/armeabi-v7a/libpldroid_beauty.so index f4b9d07..5e65e6a 100755 Binary files a/PLDroidShortVideoDemo/app/src/main/jniLibs/armeabi-v7a/libpldroid_beauty.so and b/PLDroidShortVideoDemo/app/src/main/jniLibs/armeabi-v7a/libpldroid_beauty.so differ diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable-xhdpi/green_quot.png b/PLDroidShortVideoDemo/app/src/main/res/drawable-xhdpi/green_quot.png new file mode 100644 index 0000000..685bee8 Binary files /dev/null and b/PLDroidShortVideoDemo/app/src/main/res/drawable-xhdpi/green_quot.png differ diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable-xhdpi/pink_line.png b/PLDroidShortVideoDemo/app/src/main/res/drawable-xhdpi/pink_line.png new file mode 100644 index 0000000..30f4936 Binary files /dev/null and b/PLDroidShortVideoDemo/app/src/main/res/drawable-xhdpi/pink_line.png differ diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_body.xml b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_body.xml new file mode 100644 index 0000000..ed921b8 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_body.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_left.xml b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_left.xml new file mode 100644 index 0000000..21139b8 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_left.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_middle_line.xml b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_middle_line.xml new file mode 100644 index 0000000..f2be314 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_middle_line.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_rect.xml b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_rect.xml new file mode 100644 index 0000000..f53780d --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_rect.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_right.xml b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_right.xml new file mode 100644 index 0000000..2929c04 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/res/drawable/frame_selector_right.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/res/drawable/shape_transition_selector.xml b/PLDroidShortVideoDemo/app/src/main/res/drawable/shape_transition_selector.xml new file mode 100644 index 0000000..e9a2390 --- /dev/null +++ b/PLDroidShortVideoDemo/app/src/main/res/drawable/shape_transition_selector.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PLDroidShortVideoDemo/app/src/main/res/layout/activity_main.xml b/PLDroidShortVideoDemo/app/src/main/res/layout/activity_main.xml index f6740c0..019116c 100644 --- a/PLDroidShortVideoDemo/app/src/main/res/layout/activity_main.xml +++ b/PLDroidShortVideoDemo/app/src/main/res/layout/activity_main.xml @@ -89,6 +89,14 @@ android:onClick="onClickDraftBox" android:text="@string/title_from_draft_box" /> +