Revision 9fa2835a
| app/app.iml | ||
|---|---|---|
| 27 | 27 |
</configuration> |
| 28 | 28 |
</facet> |
| 29 | 29 |
</component> |
| 30 |
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
|
| 30 |
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> |
|
| 31 | 31 |
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" /> |
| 32 | 32 |
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" /> |
| 33 | 33 |
<exclude-output /> |
| 34 | 34 |
<content url="file://$MODULE_DIR$"> |
| 35 | 35 |
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" /> |
| 36 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" /> |
|
| 36 | 37 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" /> |
| 37 | 38 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" /> |
| 38 | 39 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" /> |
| 39 | 40 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" /> |
| 40 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" /> |
|
| 41 | 41 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" /> |
| 42 | 42 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" /> |
| 43 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" /> |
|
| 43 | 44 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" /> |
| 44 | 45 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" /> |
| 45 | 46 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" /> |
| 46 | 47 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" /> |
| 47 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" /> |
|
| 48 | 48 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" /> |
| 49 | 49 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" /> |
| 50 |
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" /> |
|
| 50 | 51 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> |
| 51 | 52 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> |
| 52 | 53 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> |
| ... | ... | |
| 55 | 56 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> |
| 56 | 57 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> |
| 57 | 58 |
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" /> |
| 59 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" /> |
|
| 60 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" /> |
|
| 61 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" /> |
|
| 62 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" /> |
|
| 63 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" /> |
|
| 64 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/jni" isTestSource="true" /> |
|
| 65 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" /> |
|
| 66 |
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" /> |
|
| 58 | 67 |
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" /> |
| 59 | 68 |
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" /> |
| 60 | 69 |
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" /> |
| ... | ... | |
| 89 | 98 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" /> |
| 90 | 99 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> |
| 91 | 100 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" /> |
| 101 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" /> |
|
| 92 | 102 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> |
| 103 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes-jar" /> |
|
| 93 | 104 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> |
| 94 | 105 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" /> |
| 95 | 106 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" /> |
| ... | ... | |
| 97 | 108 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" /> |
| 98 | 109 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" /> |
| 99 | 110 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" /> |
| 111 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" /> |
|
| 100 | 112 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" /> |
| 113 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" /> |
|
| 101 | 114 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> |
| 102 | 115 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndkBuild" /> |
| 103 | 116 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" /> |
| 117 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" /> |
|
| 104 | 118 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" /> |
| 105 | 119 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> |
| 106 | 120 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" /> |
| 107 | 121 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> |
| 108 | 122 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" /> |
| 109 | 123 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" /> |
| 124 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" /> |
|
| 110 | 125 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> |
| 126 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" /> |
|
| 111 | 127 |
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" /> |
| 112 | 128 |
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> |
| 113 | 129 |
<excludeFolder url="file://$MODULE_DIR$/build/reports" /> |
| ... | ... | |
| 115 | 131 |
</content> |
| 116 | 132 |
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" /> |
| 117 | 133 |
<orderEntry type="sourceFolder" forTests="false" /> |
| 118 |
<orderEntry type="library" exported="" name="transition-25.3.1" level="project" />
|
|
| 119 |
<orderEntry type="library" exported="" name="picasso-2.6.0-" level="project" />
|
|
| 120 |
<orderEntry type="library" exported="" name="design-25.3.1" level="project" />
|
|
| 121 |
<orderEntry type="library" exported="" name="support-core-ui-25.3.1" level="project" />
|
|
| 122 |
<orderEntry type="library" exported="" name="guava-20.0" level="project" />
|
|
| 123 |
<orderEntry type="library" exported="" name="support-v4-25.3.1" level="project" />
|
|
| 124 |
<orderEntry type="library" exported="" name="support-media-compat-25.3.1" level="project" />
|
|
| 125 |
<orderEntry type="library" exported="" name="recyclerview-v7-25.3.1" level="project" />
|
|
| 126 |
<orderEntry type="library" exported="" name="support-annotations-25.3.1" level="project" />
|
|
| 127 |
<orderEntry type="library" exported="" name="appcompat-v7-25.3.1" level="project" />
|
|
| 128 |
<orderEntry type="library" exported="" name="support-vector-drawable-25.3.1" level="project" />
|
|
| 129 |
<orderEntry type="library" exported="" name="FFmpegAndroid-0.3.2" level="project" />
|
|
| 130 |
<orderEntry type="library" exported="" name="support-compat-25.3.1" level="project" />
|
|
| 131 |
<orderEntry type="library" exported="" name="support-core-utils-25.3.1" level="project" />
|
|
| 132 |
<orderEntry type="library" exported="" name="support-fragment-25.3.1" level="project" />
|
|
| 133 |
<orderEntry type="library" exported="" name="animated-vector-drawable-25.3.1" level="project" />
|
|
| 134 |
<orderEntry type="library" exported="" name="commons-codec-1.9" level="project" />
|
|
| 134 |
<orderEntry type="library" name="com.android.support:animated-vector-drawable-25.3.1" level="project" />
|
|
| 135 |
<orderEntry type="library" name="com.android.support:transition-25.3.1" level="project" />
|
|
| 136 |
<orderEntry type="library" name="com.android.support:design-25.3.1" level="project" />
|
|
| 137 |
<orderEntry type="library" name="com.writingminds:FFmpegAndroid-0.3.2" level="project" />
|
|
| 138 |
<orderEntry type="library" name="com.android.support:support-core-ui-25.3.1" level="project" />
|
|
| 139 |
<orderEntry type="library" name="com.android.support:appcompat-v7-25.3.1" level="project" />
|
|
| 140 |
<orderEntry type="library" name="com.android.support:support-compat-25.3.1" level="project" />
|
|
| 141 |
<orderEntry type="library" name="commons-codec:commons-codec:1.9@jar" level="project" />
|
|
| 142 |
<orderEntry type="library" name="com.google.guava:guava:20.0@jar" level="project" />
|
|
| 143 |
<orderEntry type="library" name="picasso-2.6.0:@aar" level="project" />
|
|
| 144 |
<orderEntry type="library" name="com.android.support:support-core-utils-25.3.1" level="project" />
|
|
| 145 |
<orderEntry type="library" name="com.android.support:support-vector-drawable-25.3.1" level="project" />
|
|
| 146 |
<orderEntry type="library" name="com.android.support:support-v4-25.3.1" level="project" />
|
|
| 147 |
<orderEntry type="library" name="com.android.support:support-fragment-25.3.1" level="project" />
|
|
| 148 |
<orderEntry type="library" name="com.android.support:recyclerview-v7-25.3.1" level="project" />
|
|
| 149 |
<orderEntry type="library" name="com.android.support:support-annotations:25.3.1@jar" level="project" />
|
|
| 150 |
<orderEntry type="library" name="com.android.support:support-media-compat-25.3.1" level="project" />
|
|
| 135 | 151 |
</component> |
| 136 | 152 |
</module> |
| app/src/main/java/net/londatiga/android/ActionItem.java | ||
|---|---|---|
| 1 |
package net.londatiga.android; |
|
| 2 |
|
|
| 3 |
import android.graphics.drawable.Drawable; |
|
| 4 |
import android.graphics.Bitmap; |
|
| 5 |
|
|
| 6 |
/** |
|
| 7 |
* Action item, displayed as menu with icon and text. |
|
| 8 |
* |
|
| 9 |
* @author Lorensius. W. L. T <lorenz@londatiga.net> |
|
| 10 |
* |
|
| 11 |
* Contributors: |
|
| 12 |
* - Kevin Peck <kevinwpeck@gmail.com> |
|
| 13 |
* |
|
| 14 |
*/ |
|
| 15 |
public class ActionItem {
|
|
| 16 |
private Drawable icon; |
|
| 17 |
private Bitmap thumb; |
|
| 18 |
private String title; |
|
| 19 |
private int actionId = -1; |
|
| 20 |
private boolean selected; |
|
| 21 |
private boolean sticky; |
|
| 22 |
|
|
| 23 |
/** |
|
| 24 |
* Constructor |
|
| 25 |
* |
|
| 26 |
* @param actionId Action id for case statements |
|
| 27 |
* @param title Title |
|
| 28 |
* @param icon Icon to use |
|
| 29 |
*/ |
|
| 30 |
public ActionItem(int actionId, String title, Drawable icon) {
|
|
| 31 |
this.title = title; |
|
| 32 |
this.icon = icon; |
|
| 33 |
this.actionId = actionId; |
|
| 34 |
} |
|
| 35 |
|
|
| 36 |
/** |
|
| 37 |
* Constructor |
|
| 38 |
*/ |
|
| 39 |
public ActionItem() {
|
|
| 40 |
this(-1, null, null); |
|
| 41 |
} |
|
| 42 |
|
|
| 43 |
/** |
|
| 44 |
* Constructor |
|
| 45 |
* |
|
| 46 |
* @param actionId Action id of the item |
|
| 47 |
* @param title Text to show for the item |
|
| 48 |
*/ |
|
| 49 |
public ActionItem(int actionId, String title) {
|
|
| 50 |
this(actionId, title, null); |
|
| 51 |
} |
|
| 52 |
|
|
| 53 |
/** |
|
| 54 |
* Constructor |
|
| 55 |
* |
|
| 56 |
* @param icon {@link Drawable} action icon
|
|
| 57 |
*/ |
|
| 58 |
public ActionItem(Drawable icon) {
|
|
| 59 |
this(-1, null, icon); |
|
| 60 |
} |
|
| 61 |
|
|
| 62 |
/** |
|
| 63 |
* Constructor |
|
| 64 |
* |
|
| 65 |
* @param actionId Action ID of item |
|
| 66 |
* @param icon {@link Drawable} action icon
|
|
| 67 |
*/ |
|
| 68 |
public ActionItem(int actionId, Drawable icon) {
|
|
| 69 |
this(actionId, null, icon); |
|
| 70 |
} |
|
| 71 |
|
|
| 72 |
/** |
|
| 73 |
* Set action title |
|
| 74 |
* |
|
| 75 |
* @param title action title |
|
| 76 |
*/ |
|
| 77 |
public void setTitle(String title) {
|
|
| 78 |
this.title = title; |
|
| 79 |
} |
|
| 80 |
|
|
| 81 |
/** |
|
| 82 |
* Get action title |
|
| 83 |
* |
|
| 84 |
* @return action title |
|
| 85 |
*/ |
|
| 86 |
public String getTitle() {
|
|
| 87 |
return this.title; |
|
| 88 |
} |
|
| 89 |
|
|
| 90 |
/** |
|
| 91 |
* Set action icon |
|
| 92 |
* |
|
| 93 |
* @param icon {@link Drawable} action icon
|
|
| 94 |
*/ |
|
| 95 |
public void setIcon(Drawable icon) {
|
|
| 96 |
this.icon = icon; |
|
| 97 |
} |
|
| 98 |
|
|
| 99 |
/** |
|
| 100 |
* Get action icon |
|
| 101 |
* @return {@link Drawable} action icon
|
|
| 102 |
*/ |
|
| 103 |
public Drawable getIcon() {
|
|
| 104 |
return this.icon; |
|
| 105 |
} |
|
| 106 |
|
|
| 107 |
/** |
|
| 108 |
* Set action id |
|
| 109 |
* |
|
| 110 |
* @param actionId Action id for this action |
|
| 111 |
*/ |
|
| 112 |
public void setActionId(int actionId) {
|
|
| 113 |
this.actionId = actionId; |
|
| 114 |
} |
|
| 115 |
|
|
| 116 |
/** |
|
| 117 |
* @return Our action id |
|
| 118 |
*/ |
|
| 119 |
public int getActionId() {
|
|
| 120 |
return actionId; |
|
| 121 |
} |
|
| 122 |
|
|
| 123 |
/** |
|
| 124 |
* Set sticky status of button |
|
| 125 |
* |
|
| 126 |
* @param sticky true for sticky, pop up sends event but does not disappear |
|
| 127 |
*/ |
|
| 128 |
public void setSticky(boolean sticky) {
|
|
| 129 |
this.sticky = sticky; |
|
| 130 |
} |
|
| 131 |
|
|
| 132 |
/** |
|
| 133 |
* @return true if button is sticky, menu stays visible after press |
|
| 134 |
*/ |
|
| 135 |
public boolean isSticky() {
|
|
| 136 |
return sticky; |
|
| 137 |
} |
|
| 138 |
|
|
| 139 |
/** |
|
| 140 |
* Set selected flag; |
|
| 141 |
* |
|
| 142 |
* @param selected Flag to indicate the item is selected |
|
| 143 |
*/ |
|
| 144 |
public void setSelected(boolean selected) {
|
|
| 145 |
this.selected = selected; |
|
| 146 |
} |
|
| 147 |
|
|
| 148 |
/** |
|
| 149 |
* Check if item is selected |
|
| 150 |
* |
|
| 151 |
* @return true or false |
|
| 152 |
*/ |
|
| 153 |
public boolean isSelected() {
|
|
| 154 |
return this.selected; |
|
| 155 |
} |
|
| 156 |
|
|
| 157 |
/** |
|
| 158 |
* Set thumb |
|
| 159 |
* |
|
| 160 |
* @param thumb Thumb image |
|
| 161 |
*/ |
|
| 162 |
public void setThumb(Bitmap thumb) {
|
|
| 163 |
this.thumb = thumb; |
|
| 164 |
} |
|
| 165 |
|
|
| 166 |
/** |
|
| 167 |
* Get thumb image |
|
| 168 |
* |
|
| 169 |
* @return Thumb image |
|
| 170 |
*/ |
|
| 171 |
public Bitmap getThumb() {
|
|
| 172 |
return this.thumb; |
|
| 173 |
} |
|
| 174 |
} |
|
| app/src/main/java/net/londatiga/android/PopupWindows.java | ||
|---|---|---|
| 1 |
package net.londatiga.android; |
|
| 2 |
|
|
| 3 |
import android.graphics.drawable.BitmapDrawable; |
|
| 4 |
import android.graphics.drawable.Drawable; |
|
| 5 |
|
|
| 6 |
import android.view.LayoutInflater; |
|
| 7 |
import android.view.MotionEvent; |
|
| 8 |
import android.view.View; |
|
| 9 |
import android.view.WindowManager; |
|
| 10 |
import android.view.View.OnTouchListener; |
|
| 11 |
|
|
| 12 |
import android.widget.PopupWindow; |
|
| 13 |
import android.content.Context; |
|
| 14 |
|
|
| 15 |
/** |
|
| 16 |
* Custom popup window. |
|
| 17 |
* |
|
| 18 |
* @author Lorensius W. L. T <lorenz@londatiga.net> |
|
| 19 |
* |
|
| 20 |
*/ |
|
| 21 |
public class PopupWindows {
|
|
| 22 |
protected Context mContext; |
|
| 23 |
protected PopupWindow mWindow; |
|
| 24 |
protected View mRootView; |
|
| 25 |
protected Drawable mBackground = null; |
|
| 26 |
protected WindowManager mWindowManager; |
|
| 27 |
|
|
| 28 |
/** |
|
| 29 |
* Constructor. |
|
| 30 |
* |
|
| 31 |
* @param context Context |
|
| 32 |
*/ |
|
| 33 |
public PopupWindows(Context context) {
|
|
| 34 |
mContext = context; |
|
| 35 |
mWindow = new PopupWindow(context); |
|
| 36 |
|
|
| 37 |
mWindow.setTouchInterceptor(new OnTouchListener() {
|
|
| 38 |
@Override |
|
| 39 |
public boolean onTouch(View v, MotionEvent event) {
|
|
| 40 |
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
|
|
| 41 |
mWindow.dismiss(); |
|
| 42 |
|
|
| 43 |
return true; |
|
| 44 |
} |
|
| 45 |
|
|
| 46 |
return false; |
|
| 47 |
} |
|
| 48 |
}); |
|
| 49 |
|
|
| 50 |
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); |
|
| 51 |
} |
|
| 52 |
|
|
| 53 |
/** |
|
| 54 |
* On dismiss |
|
| 55 |
*/ |
|
| 56 |
protected void onDismiss() {
|
|
| 57 |
} |
|
| 58 |
|
|
| 59 |
/** |
|
| 60 |
* On show |
|
| 61 |
*/ |
|
| 62 |
protected void onShow() {
|
|
| 63 |
} |
|
| 64 |
|
|
| 65 |
/** |
|
| 66 |
* On pre show |
|
| 67 |
*/ |
|
| 68 |
protected void preShow() {
|
|
| 69 |
if (mRootView == null) |
|
| 70 |
throw new IllegalStateException("setContentView was not called with a view to display.");
|
|
| 71 |
|
|
| 72 |
onShow(); |
|
| 73 |
|
|
| 74 |
if (mBackground == null) |
|
| 75 |
mWindow.setBackgroundDrawable(new BitmapDrawable()); |
|
| 76 |
else |
|
| 77 |
mWindow.setBackgroundDrawable(mBackground); |
|
| 78 |
|
|
| 79 |
mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); |
|
| 80 |
mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); |
|
| 81 |
mWindow.setTouchable(true); |
|
| 82 |
mWindow.setFocusable(true); |
|
| 83 |
mWindow.setOutsideTouchable(true); |
|
| 84 |
|
|
| 85 |
mWindow.setContentView(mRootView); |
|
| 86 |
} |
|
| 87 |
|
|
| 88 |
/** |
|
| 89 |
* Set background drawable. |
|
| 90 |
* |
|
| 91 |
* @param background Background drawable |
|
| 92 |
*/ |
|
| 93 |
public void setBackgroundDrawable(Drawable background) {
|
|
| 94 |
mBackground = background; |
|
| 95 |
} |
|
| 96 |
|
|
| 97 |
/** |
|
| 98 |
* Set content view. |
|
| 99 |
* |
|
| 100 |
* @param root Root view |
|
| 101 |
*/ |
|
| 102 |
public void setContentView(View root) {
|
|
| 103 |
mRootView = root; |
|
| 104 |
|
|
| 105 |
mWindow.setContentView(root); |
|
| 106 |
} |
|
| 107 |
|
|
| 108 |
/** |
|
| 109 |
* Set content view. |
|
| 110 |
* |
|
| 111 |
* @param layoutResID Resource id |
|
| 112 |
*/ |
|
| 113 |
public void setContentView(int layoutResID) {
|
|
| 114 |
LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
|
| 115 |
|
|
| 116 |
setContentView(inflator.inflate(layoutResID, null)); |
|
| 117 |
} |
|
| 118 |
|
|
| 119 |
/** |
|
| 120 |
* Set listener on window dismissed. |
|
| 121 |
* |
|
| 122 |
* @param listener |
|
| 123 |
*/ |
|
| 124 |
public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
|
|
| 125 |
mWindow.setOnDismissListener(listener); |
|
| 126 |
} |
|
| 127 |
|
|
| 128 |
/** |
|
| 129 |
* Dismiss the popup window. |
|
| 130 |
*/ |
|
| 131 |
public void dismiss() {
|
|
| 132 |
mWindow.dismiss(); |
|
| 133 |
} |
|
| 134 |
} |
|
| app/src/main/java/net/londatiga/android/QuickAction.java | ||
|---|---|---|
| 1 |
package net.londatiga.android; |
|
| 2 |
|
|
| 3 |
import java.util.ArrayList; |
|
| 4 |
import java.util.List; |
|
| 5 |
|
|
| 6 |
import org.witness.sscphase1.R; |
|
| 7 |
|
|
| 8 |
import android.content.Context; |
|
| 9 |
import android.graphics.Rect; |
|
| 10 |
import android.graphics.drawable.Drawable; |
|
| 11 |
import android.view.Gravity; |
|
| 12 |
import android.view.LayoutInflater; |
|
| 13 |
import android.view.View; |
|
| 14 |
import android.view.View.OnClickListener; |
|
| 15 |
import android.view.ViewGroup; |
|
| 16 |
import android.view.ViewGroup.LayoutParams; |
|
| 17 |
import android.view.animation.Animation; |
|
| 18 |
import android.view.animation.AnimationUtils; |
|
| 19 |
import android.view.animation.Interpolator; |
|
| 20 |
import android.widget.ImageView; |
|
| 21 |
import android.widget.PopupWindow.OnDismissListener; |
|
| 22 |
import android.widget.TextView; |
|
| 23 |
|
|
| 24 |
/** |
|
| 25 |
* QuickAction dialog. |
|
| 26 |
* |
|
| 27 |
* @author Lorensius W. L. T <lorenz@londatiga.net> |
|
| 28 |
* |
|
| 29 |
* Contributors: |
|
| 30 |
* - Kevin Peck <kevinwpeck@gmail.com> |
|
| 31 |
*/ |
|
| 32 |
public class QuickAction extends PopupWindows implements OnDismissListener {
|
|
| 33 |
private ImageView mArrowUp; |
|
| 34 |
private ImageView mArrowDown; |
|
| 35 |
private Animation mTrackAnim; |
|
| 36 |
private LayoutInflater inflater; |
|
| 37 |
private ViewGroup mTrack; |
|
| 38 |
private OnActionItemClickListener mItemClickListener; |
|
| 39 |
private OnDismissListener mDismissListener; |
|
| 40 |
|
|
| 41 |
private List<ActionItem> mActionItemList = new ArrayList<ActionItem>(); |
|
| 42 |
|
|
| 43 |
private boolean mDidAction; |
|
| 44 |
private boolean mAnimateTrack; |
|
| 45 |
|
|
| 46 |
private int mChildPos; |
|
| 47 |
private int mAnimStyle; |
|
| 48 |
|
|
| 49 |
public static final int ANIM_GROW_FROM_LEFT = 1; |
|
| 50 |
public static final int ANIM_GROW_FROM_RIGHT = 2; |
|
| 51 |
public static final int ANIM_GROW_FROM_CENTER = 3; |
|
| 52 |
public static final int ANIM_AUTO = 4; |
|
| 53 |
|
|
| 54 |
/** |
|
| 55 |
* Constructor. |
|
| 56 |
* |
|
| 57 |
* @param context Context |
|
| 58 |
*/ |
|
| 59 |
public QuickAction(Context context) {
|
|
| 60 |
super(context); |
|
| 61 |
|
|
| 62 |
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
|
| 63 |
|
|
| 64 |
mTrackAnim = AnimationUtils.loadAnimation(context, R.anim.rail); |
|
| 65 |
|
|
| 66 |
mTrackAnim.setInterpolator(new Interpolator() {
|
|
| 67 |
public float getInterpolation(float t) {
|
|
| 68 |
// Pushes past the target area, then snaps back into place. |
|
| 69 |
// Equation for graphing: 1.2-((x*1.6)-1.1)^2 |
|
| 70 |
final float inner = (t * 1.55f) - 1.1f; |
|
| 71 |
|
|
| 72 |
return 1.2f - inner * inner; |
|
| 73 |
} |
|
| 74 |
}); |
|
| 75 |
|
|
| 76 |
setRootViewId(R.layout.quickaction); |
|
| 77 |
|
|
| 78 |
mAnimStyle = ANIM_AUTO; |
|
| 79 |
mAnimateTrack = true; |
|
| 80 |
mChildPos = 0; |
|
| 81 |
} |
|
| 82 |
|
|
| 83 |
/** |
|
| 84 |
* Get action item at an index |
|
| 85 |
* |
|
| 86 |
* @param index Index of item (position from callback) |
|
| 87 |
* |
|
| 88 |
* @return Action Item at the position |
|
| 89 |
*/ |
|
| 90 |
public ActionItem getActionItem(int index) {
|
|
| 91 |
return mActionItemList.get(index); |
|
| 92 |
} |
|
| 93 |
|
|
| 94 |
/** |
|
| 95 |
* Set root view. |
|
| 96 |
* |
|
| 97 |
* @param id Layout resource id |
|
| 98 |
*/ |
|
| 99 |
public void setRootViewId(int id) {
|
|
| 100 |
mRootView = (ViewGroup) inflater.inflate(id, null); |
|
| 101 |
mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks); |
|
| 102 |
|
|
| 103 |
mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down); |
|
| 104 |
mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up); |
|
| 105 |
|
|
| 106 |
//This was previously defined on show() method, moved here to prevent force close that occured |
|
| 107 |
//when tapping fastly on a view to show quickaction dialog. |
|
| 108 |
//Thanx to zammbi (github.com/zammbi) |
|
| 109 |
mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); |
|
| 110 |
|
|
| 111 |
setContentView(mRootView); |
|
| 112 |
} |
|
| 113 |
|
|
| 114 |
/** |
|
| 115 |
* Animate track. |
|
| 116 |
* |
|
| 117 |
* @param mAnimateTrack flag to animate track |
|
| 118 |
*/ |
|
| 119 |
public void mAnimateTrack(boolean mAnimateTrack) {
|
|
| 120 |
this.mAnimateTrack = mAnimateTrack; |
|
| 121 |
} |
|
| 122 |
|
|
| 123 |
/** |
|
| 124 |
* Set animation style. |
|
| 125 |
* |
|
| 126 |
* @param mAnimStyle animation style, default is set to ANIM_AUTO |
|
| 127 |
*/ |
|
| 128 |
public void setAnimStyle(int mAnimStyle) {
|
|
| 129 |
this.mAnimStyle = mAnimStyle; |
|
| 130 |
} |
|
| 131 |
|
|
| 132 |
/** |
|
| 133 |
* Add action item |
|
| 134 |
* |
|
| 135 |
* @param action {@link ActionItem}
|
|
| 136 |
*/ |
|
| 137 |
public void addActionItem(ActionItem action) {
|
|
| 138 |
mActionItemList.add(action); |
|
| 139 |
|
|
| 140 |
String title = action.getTitle(); |
|
| 141 |
Drawable icon = action.getIcon(); |
|
| 142 |
|
|
| 143 |
View container = (View) inflater.inflate(R.layout.action_item, null); |
|
| 144 |
|
|
| 145 |
ImageView img = (ImageView) container.findViewById(R.id.iv_icon); |
|
| 146 |
TextView text = (TextView) container.findViewById(R.id.tv_title); |
|
| 147 |
|
|
| 148 |
if (icon != null) {
|
|
| 149 |
img.setImageDrawable(icon); |
|
| 150 |
} else {
|
|
| 151 |
img.setVisibility(View.GONE); |
|
| 152 |
} |
|
| 153 |
|
|
| 154 |
if (title != null) {
|
|
| 155 |
text.setText(title); |
|
| 156 |
} else {
|
|
| 157 |
text.setVisibility(View.GONE); |
|
| 158 |
} |
|
| 159 |
|
|
| 160 |
final int pos = mChildPos; |
|
| 161 |
final int actionId = action.getActionId(); |
|
| 162 |
|
|
| 163 |
container.setOnClickListener(new OnClickListener() {
|
|
| 164 |
@Override |
|
| 165 |
public void onClick(View v) {
|
|
| 166 |
if (mItemClickListener != null) {
|
|
| 167 |
mItemClickListener.onItemClick(QuickAction.this, pos, actionId); |
|
| 168 |
} |
|
| 169 |
|
|
| 170 |
if (!getActionItem(pos).isSticky()) {
|
|
| 171 |
mDidAction = true; |
|
| 172 |
|
|
| 173 |
//workaround for transparent background bug |
|
| 174 |
//thx to Roman Wozniak <roman.wozniak@gmail.com> |
|
| 175 |
v.post(new Runnable() {
|
|
| 176 |
@Override |
|
| 177 |
public void run() {
|
|
| 178 |
dismiss(); |
|
| 179 |
} |
|
| 180 |
}); |
|
| 181 |
} |
|
| 182 |
} |
|
| 183 |
}); |
|
| 184 |
|
|
| 185 |
container.setFocusable(true); |
|
| 186 |
container.setClickable(true); |
|
| 187 |
|
|
| 188 |
mTrack.addView(container, mChildPos+1); |
|
| 189 |
|
|
| 190 |
mChildPos++; |
|
| 191 |
} |
|
| 192 |
|
|
| 193 |
public void setOnActionItemClickListener(OnActionItemClickListener listener) {
|
|
| 194 |
mItemClickListener = listener; |
|
| 195 |
} |
|
| 196 |
|
|
| 197 |
/** |
|
| 198 |
* Show popup mWindow |
|
| 199 |
*/ |
|
| 200 |
public void show (View anchor, int locX, int locY) {
|
|
| 201 |
preShow(); |
|
| 202 |
|
|
| 203 |
//int[] location = new int[2]; |
|
| 204 |
|
|
| 205 |
|
|
| 206 |
mDidAction = false; |
|
| 207 |
|
|
| 208 |
// anchor.getLocationOnScreen(location); |
|
| 209 |
|
|
| 210 |
Rect anchorRect = new Rect(locX, locY, locX + anchor.getWidth(), locY |
|
| 211 |
+ anchor.getHeight()); |
|
| 212 |
|
|
| 213 |
//mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); |
|
| 214 |
mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); |
|
| 215 |
|
|
| 216 |
int rootWidth = mRootView.getMeasuredWidth(); |
|
| 217 |
int rootHeight = mRootView.getMeasuredHeight(); |
|
| 218 |
|
|
| 219 |
int screenWidth = mWindowManager.getDefaultDisplay().getWidth(); |
|
| 220 |
//int screenHeight = mWindowManager.getDefaultDisplay().getHeight(); |
|
| 221 |
|
|
| 222 |
int xPos = (screenWidth - rootWidth) / 2; |
|
| 223 |
int yPos = anchorRect.top - rootHeight; |
|
| 224 |
|
|
| 225 |
boolean onTop = true; |
|
| 226 |
|
|
| 227 |
// display on bottom |
|
| 228 |
if (rootHeight > anchor.getTop()) {
|
|
| 229 |
yPos = anchorRect.bottom; |
|
| 230 |
onTop = false; |
|
| 231 |
} |
|
| 232 |
|
|
| 233 |
showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), anchorRect.centerX()); |
|
| 234 |
|
|
| 235 |
setAnimationStyle(screenWidth, anchorRect.centerX(), onTop); |
|
| 236 |
|
|
| 237 |
mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos); |
|
| 238 |
|
|
| 239 |
if (mAnimateTrack) mTrack.startAnimation(mTrackAnim); |
|
| 240 |
} |
|
| 241 |
|
|
| 242 |
/** |
|
| 243 |
* Set animation style |
|
| 244 |
* |
|
| 245 |
* @param screenWidth Screen width |
|
| 246 |
* @param requestedX distance from left screen |
|
| 247 |
* @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor and vice versa |
|
| 248 |
*/ |
|
| 249 |
private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
|
|
| 250 |
int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2; |
|
| 251 |
|
|
| 252 |
switch (mAnimStyle) {
|
|
| 253 |
case ANIM_GROW_FROM_LEFT: |
|
| 254 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left); |
|
| 255 |
break; |
|
| 256 |
|
|
| 257 |
case ANIM_GROW_FROM_RIGHT: |
|
| 258 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right); |
|
| 259 |
break; |
|
| 260 |
|
|
| 261 |
case ANIM_GROW_FROM_CENTER: |
|
| 262 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center); |
|
| 263 |
break; |
|
| 264 |
|
|
| 265 |
case ANIM_AUTO: |
|
| 266 |
if (arrowPos <= screenWidth/4) {
|
|
| 267 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left); |
|
| 268 |
} else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
|
|
| 269 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center); |
|
| 270 |
} else {
|
|
| 271 |
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopDownMenu_Right : R.style.Animations_PopDownMenu_Right); |
|
| 272 |
} |
|
| 273 |
|
|
| 274 |
break; |
|
| 275 |
} |
|
| 276 |
} |
|
| 277 |
|
|
| 278 |
/** |
|
| 279 |
* Show arrow |
|
| 280 |
* |
|
| 281 |
* @param whichArrow arrow type resource id |
|
| 282 |
* @param requestedX distance from left screen |
|
| 283 |
*/ |
|
| 284 |
private void showArrow(int whichArrow, int requestedX) {
|
|
| 285 |
final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown; |
|
| 286 |
final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp; |
|
| 287 |
|
|
| 288 |
final int arrowWidth = mArrowUp.getMeasuredWidth(); |
|
| 289 |
|
|
| 290 |
showArrow.setVisibility(View.VISIBLE); |
|
| 291 |
|
|
| 292 |
ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams(); |
|
| 293 |
|
|
| 294 |
param.leftMargin = requestedX - arrowWidth / 2; |
|
| 295 |
|
|
| 296 |
hideArrow.setVisibility(View.INVISIBLE); |
|
| 297 |
} |
|
| 298 |
|
|
| 299 |
/** |
|
| 300 |
* Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed |
|
| 301 |
* by clicking outside the dialog or clicking on sticky item. |
|
| 302 |
*/ |
|
| 303 |
public void setOnDismissListener(QuickAction.OnDismissListener listener) {
|
|
| 304 |
setOnDismissListener(this); |
|
| 305 |
|
|
| 306 |
mDismissListener = listener; |
|
| 307 |
} |
|
| 308 |
|
|
| 309 |
@Override |
|
| 310 |
public void onDismiss() {
|
|
| 311 |
if (!mDidAction && mDismissListener != null) {
|
|
| 312 |
mDismissListener.onDismiss(); |
|
| 313 |
} |
|
| 314 |
} |
|
| 315 |
|
|
| 316 |
/** |
|
| 317 |
* Listener for item click |
|
| 318 |
* |
|
| 319 |
*/ |
|
| 320 |
public interface OnActionItemClickListener {
|
|
| 321 |
public abstract void onItemClick(QuickAction source, int pos, int actionId); |
|
| 322 |
} |
|
| 323 |
|
|
| 324 |
/** |
|
| 325 |
* Listener for window dismiss |
|
| 326 |
* |
|
| 327 |
*/ |
|
| 328 |
public interface OnDismissListener {
|
|
| 329 |
public abstract void onDismiss(); |
|
| 330 |
} |
|
| 331 |
} |
|
| app/src/main/java/org/witness/ssc/video/FFMPEGWrapper.java | ||
|---|---|---|
| 20 | 20 |
public class FFMPEGWrapper {
|
| 21 | 21 |
|
| 22 | 22 |
Context context; |
| 23 |
FFmpeg ffmpeg; |
|
| 23 | 24 |
|
| 24 | 25 |
public FFMPEGWrapper(Context _context) throws FileNotFoundException, IOException {
|
| 25 | 26 |
context = _context; |
| 26 | 27 |
|
| 27 |
FFmpeg ffmpeg = FFmpeg.getInstance(context); |
|
| 28 |
try {
|
|
| 28 |
ffmpeg = FFmpeg.getInstance(context); |
|
| 29 |
|
|
| 30 |
try {
|
|
| 29 | 31 |
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
|
| 30 | 32 |
|
| 31 | 33 |
@Override |
| ... | ... | |
| 54 | 56 |
|
| 55 | 57 |
|
| 56 | 58 |
public void processVideo( |
| 57 |
ArrayList<RegionTrail> regionTrails, File inputFile, File outputFile, int frameRate, int mDuration, int mOutputLength,
|
|
| 59 |
ArrayList<RegionTrail> regionTrails, File inputFile, File outputFile, int frameRate, float startTime, float duration,
|
|
| 58 | 60 |
boolean compressVideo, int obscureVideoAmount, int obscureAudioAmount, ExecuteBinaryResponseHandler listener) throws Exception {
|
| 59 | 61 |
|
| 60 | 62 |
DecimalFormat df = new DecimalFormat("####0.00");
|
| ... | ... | |
| 65 | 67 |
alCmds.add("-i");
|
| 66 | 68 |
alCmds.add(inputFile.getCanonicalPath()); |
| 67 | 69 |
|
| 68 |
if (mOutputLength > 0)
|
|
| 70 |
if (duration > 0)
|
|
| 69 | 71 |
{
|
| 72 |
alCmds.add("-ss");
|
|
| 73 |
alCmds.add(df.format(startTime)); |
|
| 74 |
|
|
| 70 | 75 |
alCmds.add("-t");
|
| 71 |
alCmds.add(mOutputLength+"");
|
|
| 76 |
alCmds.add(df.format(duration));
|
|
| 72 | 77 |
} |
| 73 | 78 |
|
| 74 | 79 |
if (frameRate > 0) |
| ... | ... | |
| 119 | 124 |
if (trail.isDoTweening() && trail.getRegionCount() > 1) {
|
| 120 | 125 |
int timeInc = 100; |
| 121 | 126 |
|
| 122 |
for (int i = 0; i < mDuration; i = i + timeInc) {
|
|
| 127 |
for (int i = 0; i < ((int)duration); i = i + timeInc) {
|
|
| 123 | 128 |
ObscureRegion or = trail.getCurrentRegion(i, trail.isDoTweening()); |
| 124 | 129 |
if (or != null) {
|
| 125 | 130 |
|
| ... | ... | |
| 131 | 136 |
float timeStart = ((float) or.timeStamp) / 1000f; |
| 132 | 137 |
float timeStop = (((float) or.timeStamp) + 100) / 1000f; |
| 133 | 138 |
|
| 134 |
float timeEnd = ((float) mDuration) / 1000f;
|
|
| 139 |
float timeEnd = duration / 1000f;
|
|
| 135 | 140 |
timeStop = Math.max(timeStop, timeEnd); |
| 136 | 141 |
|
| 137 | 142 |
filters.append("drawbox=x=" + x + ":y=" + y
|
| ... | ... | |
| 184 | 189 |
try {
|
| 185 | 190 |
|
| 186 | 191 |
|
| 187 |
FFmpeg ffmpeg = FFmpeg.getInstance(context); |
|
| 188 | 192 |
// to execute "ffmpeg -version" command you just need to pass "-version" |
| 189 | 193 |
ffmpeg.execute(cmd,listener); |
| 190 | 194 |
} catch (FFmpegCommandAlreadyRunningException e) {
|
| ... | ... | |
| 251 | 255 |
|
| 252 | 256 |
|
| 253 | 257 |
} |
| 254 |
|
|
| 258 |
|
|
| 259 |
public FFmpeg getFFMPEG () |
|
| 260 |
{
|
|
| 261 |
return ffmpeg; |
|
| 262 |
} |
|
| 255 | 263 |
|
| 256 | 264 |
} |
| 257 | 265 |
|
| app/src/main/java/org/witness/ssc/video/VideoEditor.java | ||
|---|---|---|
| 64 | 64 |
import android.widget.ImageButton; |
| 65 | 65 |
import android.widget.ImageView; |
| 66 | 66 |
import android.widget.MediaController; |
| 67 |
import android.widget.ProgressBar; |
|
| 67 | 68 |
import android.widget.SeekBar; |
| 68 | 69 |
import android.widget.Toast; |
| 69 | 70 |
import android.widget.VideoView; |
| 70 | 71 |
|
| 71 | 72 |
import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler; |
| 72 | 73 |
|
| 73 |
import net.londatiga.android.ActionItem; |
|
| 74 |
import net.londatiga.android.QuickAction; |
|
| 75 |
import net.londatiga.android.QuickAction.OnActionItemClickListener; |
|
| 76 | 74 |
|
| 77 | 75 |
import org.witness.securesmartcam.detect.AndroidFaceDetection; |
| 78 | 76 |
import org.witness.securesmartcam.detect.DetectedFace; |
| ... | ... | |
| 96 | 94 |
OnBufferingUpdateListener, OnPreparedListener, OnSeekCompleteListener, |
| 97 | 95 |
OnVideoSizeChangedListener, SurfaceHolder.Callback, |
| 98 | 96 |
MediaController.MediaPlayerControl, OnTouchListener, |
| 99 |
InOutPlayheadSeekBarChangeListener, OnActionItemClickListener {
|
|
| 97 |
InOutPlayheadSeekBarChangeListener {
|
|
| 100 | 98 |
|
| 101 | 99 |
public static final String LOGTAG = ObscuraApp.TAG; |
| 102 | 100 |
|
| ... | ... | |
| 111 | 109 |
|
| 112 | 110 |
private final static int HUMAN_OFFSET_BUFFER = 50; |
| 113 | 111 |
|
| 114 |
ProgressDialog progressDialog; |
|
| 115 | 112 |
int completeActionFlag = 3; |
| 116 | 113 |
|
| 117 | 114 |
Uri originalVideoUri; |
| ... | ... | |
| 140 | 137 |
|
| 141 | 138 |
Bitmap bitmapPixel; |
| 142 | 139 |
|
| 143 |
InOutPlayheadSeekBar progressBar;
|
|
| 140 |
InOutPlayheadSeekBar mVideoSeekbar;
|
|
| 144 | 141 |
//RegionBarArea regionBarArea; |
| 145 | 142 |
|
| 146 | 143 |
int videoWidth = 0; |
| ... | ... | |
| 181 | 178 |
private final static String DEFAULT_OUT_WIDTH = "480"; |
| 182 | 179 |
private final static String DEFAULT_OUT_HEIGHT = "320"; |
| 183 | 180 |
|
| 181 |
private ProgressBar mProgressBar; |
|
| 184 | 182 |
|
| 185 | 183 |
private Handler mHandler = new Handler() {
|
| 186 | 184 |
public void handleMessage(Message msg) {
|
| ... | ... | |
| 201 | 199 |
Date dateProgress = sdf.parse(time); |
| 202 | 200 |
long progress = dateProgress.getSeconds()*1000; |
| 203 | 201 |
int percentComplete = (int)((((float)progress)/((float)mDuration))*100f); |
| 204 |
progressDialog.setProgress(percentComplete);
|
|
| 202 |
mProgressBar.setProgress(percentComplete);
|
|
| 205 | 203 |
} |
| 206 | 204 |
} |
| 207 | 205 |
catch (Exception e) |
| ... | ... | |
| 215 | 213 |
mCancelled = true; |
| 216 | 214 |
mAutoDetectEnabled = false; |
| 217 | 215 |
killVideoProcessor(); |
| 218 |
|
|
| 216 |
mProgressBar.setVisibility(View.GONE); |
|
| 219 | 217 |
break; |
| 220 | 218 |
|
| 221 | 219 |
case 3: //completed |
| 222 |
progressDialog.dismiss(); |
|
| 223 | 220 |
askPostProcessAction(); |
| 224 | 221 |
|
| 222 |
mProgressBar.setVisibility(View.GONE); |
|
| 225 | 223 |
break; |
| 226 | 224 |
|
| 227 | 225 |
case 5: |
| ... | ... | |
| 312 | 310 |
mediaPlayer.prepare(); |
| 313 | 311 |
mDuration = mediaPlayer.getDuration(); |
| 314 | 312 |
|
| 315 |
progressBar.setMax(mDuration);
|
|
| 313 |
mVideoSeekbar.setMax(mDuration);
|
|
| 316 | 314 |
|
| 317 | 315 |
} catch (Exception e) {
|
| 318 | 316 |
Log.v(LOGTAG, "IllegalStateException " + e.getMessage()); |
| ... | ... | |
| 375 | 373 |
mediaPlayer.prepare(); |
| 376 | 374 |
mDuration = mediaPlayer.getDuration(); |
| 377 | 375 |
|
| 378 |
progressBar.setMax(mDuration);
|
|
| 376 |
mVideoSeekbar.setMax(mDuration);
|
|
| 379 | 377 |
|
| 380 | 378 |
} catch (Exception e) {
|
| 381 | 379 |
Log.v(LOGTAG, "IllegalStateException " + e.getMessage()); |
| ... | ... | |
| 462 | 460 |
private void beginAutoDetect() {
|
| 463 | 461 |
mAutoDetectEnabled = true; |
| 464 | 462 |
|
| 465 |
progressDialog = new ProgressDialog(this); |
|
| 466 |
progressDialog = ProgressDialog.show(this, "", "Detecting faces...", true, true); |
|
| 467 |
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); |
|
| 468 |
progressDialog.setCancelable(true); |
|
| 469 |
Message msg = mHandler.obtainMessage(2); |
|
| 470 |
msg.getData().putString("status", "cancelled");
|
|
| 471 |
progressDialog.setCancelMessage(msg); |
|
| 472 |
|
|
| 473 |
progressDialog.show(); |
|
| 474 |
|
|
| 475 | 463 |
new Thread(doAutoDetect).start(); |
| 476 | 464 |
|
| 477 | 465 |
} |
| ... | ... | |
| 623 | 611 |
try {
|
| 624 | 612 |
seekTo(f); |
| 625 | 613 |
|
| 626 |
progressBar.setProgress(mediaPlayer.getCurrentPosition());
|
|
| 614 |
mVideoSeekbar.setProgress(mediaPlayer.getCurrentPosition());
|
|
| 627 | 615 |
|
| 628 | 616 |
//Bitmap bmp = getVideoFrame(rPath,f*1000); |
| 629 | 617 |
|
| ... | ... | |
| 668 | 656 |
try {
|
| 669 | 657 |
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
|
| 670 | 658 |
int curr = mediaPlayer.getCurrentPosition(); |
| 671 |
progressBar.setProgress(curr);
|
|
| 659 |
mVideoSeekbar.setProgress(curr);
|
|
| 672 | 660 |
updateRegionDisplay(curr); |
| 673 | 661 |
mHandler.post(this); |
| 674 | 662 |
} |
| ... | ... | |
| 835 | 823 |
|
| 836 | 824 |
boolean handled = false; |
| 837 | 825 |
|
| 838 |
if (v == progressBar) {
|
|
| 826 |
if (v == mVideoSeekbar) {
|
|
| 839 | 827 |
|
| 840 | 828 |
if (currentUri != originalVideoUri) |
| 841 | 829 |
{
|
| ... | ... | |
| 853 | 841 |
} |
| 854 | 842 |
|
| 855 | 843 |
|
| 856 |
mediaPlayer.seekTo(progressBar.getProgress());
|
|
| 844 |
mediaPlayer.seekTo(mVideoSeekbar.getProgress());
|
|
| 857 | 845 |
// Attempt to get the player to update it's view - NOT WORKING |
| 858 | 846 |
} |
| 859 | 847 |
|
| ... | ... | |
| 1042 | 1030 |
|
| 1043 | 1031 |
case R.id.menu_save: |
| 1044 | 1032 |
|
| 1045 |
|
|
| 1033 |
resetMediaPlayer(originalVideoUri); |
|
| 1046 | 1034 |
processVideo(false); |
| 1047 | 1035 |
|
| 1048 | 1036 |
return true; |
| ... | ... | |
| 1068 | 1056 |
|
| 1069 | 1057 |
PowerManager.WakeLock wl; |
| 1070 | 1058 |
|
| 1071 |
private void processVideo(boolean isPreview) {
|
|
| 1059 |
private synchronized void processVideo(boolean isPreview) {
|
|
| 1060 |
|
|
| 1061 |
if (ffmpeg != null |
|
| 1062 |
&& ffmpeg.getFFMPEG().isFFmpegCommandRunning()) |
|
| 1063 |
ffmpeg.getFFMPEG().killRunningProcesses(); |
|
| 1072 | 1064 |
|
| 1073 | 1065 |
mIsPreview = isPreview; |
| 1074 | 1066 |
|
| 1067 |
mProgressBar.setVisibility(View.VISIBLE); |
|
| 1068 |
mProgressBar.setProgress(0); |
|
| 1069 |
|
|
| 1075 | 1070 |
if (isPreview) |
| 1076 | 1071 |
{
|
| 1077 | 1072 |
saveFile = new File(fileExternDir,"obscuracam-preview-tmp." + outFormat); |
| 1078 | 1073 |
} |
| 1079 | 1074 |
else {
|
| 1075 |
if (saveFile != null |
|
| 1076 |
&& saveFile.exists() && saveFile.getName().contains("preview"))
|
|
| 1077 |
saveFile.delete(); |
|
| 1078 |
|
|
| 1080 | 1079 |
createCleanSavePath(outFormat); |
| 1080 |
|
|
| 1081 |
mSnackbar = Snackbar.make(findViewById(R.id.frameRoot), R.string.processing, Snackbar.LENGTH_INDEFINITE); |
|
| 1082 |
mSnackbar.show(); |
|
| 1081 | 1083 |
} |
| 1082 | 1084 |
|
| 1083 | 1085 |
mCancelled = false; |
| 1084 | 1086 |
|
| 1085 | 1087 |
mediaPlayer.pause(); |
| 1086 | 1088 |
|
| 1087 |
progressDialog = new ProgressDialog(this); |
|
| 1088 |
progressDialog.setMessage("Processing. Please wait...");
|
|
| 1089 |
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); |
|
| 1090 |
progressDialog.setMax(100); |
|
| 1091 |
progressDialog.setProgress(0); |
|
| 1092 |
progressDialog.setCancelable(true); |
|
| 1093 |
|
|
| 1094 |
Message msg = mHandler.obtainMessage(2); |
|
| 1095 |
msg.getData().putString("status", "cancelled");
|
|
| 1096 |
progressDialog.setCancelMessage(msg); |
|
| 1097 |
|
|
| 1098 |
progressDialog.show(); |
|
| 1099 |
|
|
| 1100 | 1089 |
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); |
| 1101 | 1090 |
wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); |
| 1102 | 1091 |
wl.acquire(); |
| ... | ... | |
| 1105 | 1094 |
if (ffmpeg == null) |
| 1106 | 1095 |
ffmpeg = new FFMPEGWrapper(VideoEditor.this.getBaseContext()); |
| 1107 | 1096 |
|
| 1108 |
int outputLength = -1; |
|
| 1109 | 1097 |
int frameRate = 0; |
| 1110 | 1098 |
|
| 1099 |
float startTime = ((float)mediaPlayer.getCurrentPosition())/1000f; |
|
| 1100 |
float duration = (float)mDuration/1000f; |
|
| 1101 |
|
|
| 1111 | 1102 |
if (isPreview) {
|
| 1112 | 1103 |
frameRate = 1; |
| 1113 |
outputLength = Math.min(mDuration, 5); |
|
| 1114 |
mDuration = outputLength; |
|
| 1104 |
duration = Math.min(duration - startTime, 1f); |
|
| 1115 | 1105 |
} |
| 1106 |
|
|
| 1116 | 1107 |
else if (mObscureVideoAmount > 0) |
| 1117 | 1108 |
{
|
| 1118 |
frameRate = 15;
|
|
| 1109 |
frameRate = 3;
|
|
| 1119 | 1110 |
} |
| 1120 | 1111 |
|
| 1121 | 1112 |
// Could make some high/low quality presets |
| 1122 | 1113 |
ffmpeg.processVideo(obscureTrails, recordingFile, saveFile, |
| 1123 |
frameRate, mDuration, outputLength, mCompressVideo, mObscureVideoAmount, mObscureAudioAmount,
|
|
| 1114 |
frameRate, startTime, duration, mCompressVideo, mObscureVideoAmount, mObscureAudioAmount,
|
|
| 1124 | 1115 |
new ExecuteBinaryResponseHandler() {
|
| 1125 | 1116 |
|
| 1126 | 1117 |
@Override |
| ... | ... | |
| 1187 | 1178 |
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(saveFile))); |
| 1188 | 1179 |
} |
| 1189 | 1180 |
|
| 1181 |
Snackbar mSnackbar; |
|
| 1182 |
|
|
| 1190 | 1183 |
private void askPostProcessAction() {
|
| 1191 | 1184 |
if (saveFile != null && saveFile.exists()) {
|
| 1192 | 1185 |
|
| ... | ... | |
| 1194 | 1187 |
start(); |
| 1195 | 1188 |
|
| 1196 | 1189 |
if (!mIsPreview) {
|
| 1197 |
Snackbar snackbar = Snackbar.make(findViewById(R.id.frameRoot), R.string.processing_complete, Snackbar.LENGTH_LONG); |
|
| 1198 |
snackbar.setAction("Open", new OnClickListener() {
|
|
| 1190 |
|
|
| 1191 |
if (mSnackbar != null) |
|
| 1192 |
{
|
|
| 1193 |
mSnackbar.dismiss(); |
|
| 1194 |
mSnackbar = null; |
|
| 1195 |
} |
|
| 1196 |
|
|
| 1197 |
mSnackbar = Snackbar.make(findViewById(R.id.frameRoot), R.string.processing_complete, Snackbar.LENGTH_LONG); |
|
| 1198 |
mSnackbar.setAction("Open", new OnClickListener() {
|
|
| 1199 | 1199 |
@Override |
| 1200 | 1200 |
public void onClick(View view) {
|
| 1201 | 1201 |
playVideoExternal(); |
| 1202 | 1202 |
} |
| 1203 | 1203 |
}); |
| 1204 |
snackbar.show();
|
|
| 1204 |
mSnackbar.show();
|
|
| 1205 | 1205 |
} |
| 1206 | 1206 |
} |
| 1207 | 1207 |
|
| ... | ... | |
| 1313 | 1313 |
|
| 1314 | 1314 |
videoView = (VideoView) this.findViewById(R.id.SurfaceView); |
| 1315 | 1315 |
|
| 1316 |
mProgressBar = (ProgressBar) this.findViewById(R.id.progress_spinner); |
|
| 1317 |
|
|
| 1316 | 1318 |
regionsView = (ImageView) this.findViewById(R.id.VideoEditorImageView); |
| 1317 | 1319 |
regionsView.setOnClickListener(new OnClickListener() {
|
| 1318 | 1320 |
@Override |
| ... | ... | |
| 1320 | 1322 |
resetMediaPlayer(originalVideoUri); |
| 1321 | 1323 |
} |
| 1322 | 1324 |
}); |
| 1323 |
// regionsView.setOnTouchListener(this);
|
|
| 1325 |
regionsView.setOnTouchListener(this); |
|
| 1324 | 1326 |
|
| 1325 | 1327 |
surfaceHolder = videoView.getHolder(); |
| 1326 | 1328 |
|
| ... | ... | |
| 1329 | 1331 |
|
| 1330 | 1332 |
currentDisplay = getWindowManager().getDefaultDisplay(); |
| 1331 | 1333 |
|
| 1332 |
progressBar = (InOutPlayheadSeekBar) this.findViewById(R.id.InOutPlayheadSeekBar);
|
|
| 1334 |
mVideoSeekbar = (InOutPlayheadSeekBar) this.findViewById(R.id.InOutPlayheadSeekBar);
|
|
| 1333 | 1335 |
|
| 1334 |
progressBar.setIndeterminate(false);
|
|
| 1335 |
progressBar.setSecondaryProgress(0);
|
|
| 1336 |
progressBar.setProgress(0);
|
|
| 1337 |
progressBar.setInOutPlayheadSeekBarChangeListener(this);
|
|
| 1338 |
progressBar.setThumbsInactive();
|
|
| 1339 |
progressBar.setOnTouchListener(this);
|
|
| 1336 |
mVideoSeekbar.setIndeterminate(false);
|
|
| 1337 |
mVideoSeekbar.setSecondaryProgress(0);
|
|
| 1338 |
mVideoSeekbar.setProgress(0);
|
|
| 1339 |
mVideoSeekbar.setInOutPlayheadSeekBarChangeListener(this);
|
|
| 1340 |
mVideoSeekbar.setThumbsInactive();
|
|
| 1341 |
mVideoSeekbar.setOnTouchListener(this);
|
|
| 1340 | 1342 |
|
| 1341 | 1343 |
playPauseButton = (ImageButton) this.findViewById(R.id.PlayPauseImageButton); |
| 1342 | 1344 |
playPauseButton.setOnClickListener(new OnClickListener() {
|
| ... | ... | |
| 1347 | 1349 |
playPauseButton.setImageDrawable(getResources().getDrawable(android.R.drawable.ic_media_play)); |
| 1348 | 1350 |
mAutoDetectEnabled = false; |
| 1349 | 1351 |
} else {
|
| 1352 |
if (currentUri != originalVideoUri) |
|
| 1353 |
{
|
|
| 1354 |
resetMediaPlayer(originalVideoUri); |
|
| 1355 |
seekTo(0); |
|
| 1356 |
} |
|
| 1350 | 1357 |
start(); |
| 1351 | 1358 |
|
| 1352 | 1359 |
|
| ... | ... | |
| 1376 | 1383 |
} |
| 1377 | 1384 |
});**/ |
| 1378 | 1385 |
|
| 1379 |
findViewById(R.id.button_preview).setOnClickListener(new OnClickListener() {
|
|
| 1380 |
@Override |
|
| 1381 |
public void onClick(View view) {
|
|
| 1382 |
processVideo(true); |
|
| 1383 |
} |
|
| 1384 |
}); |
|
| 1385 |
|
|
| 1386 | 1386 |
((SeekBar)findViewById(R.id.seekbar_video_obscure)).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
| 1387 | 1387 |
@Override |
| 1388 | 1388 |
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
| ... | ... | |
| 1393 | 1393 |
} |
| 1394 | 1394 |
|
| 1395 | 1395 |
mObscureVideoAmount = i; |
| 1396 |
|
|
| 1396 | 1397 |
} |
| 1397 | 1398 |
|
| 1398 | 1399 |
@Override |
| ... | ... | |
| 1403 | 1404 |
@Override |
| 1404 | 1405 |
public void onStopTrackingTouch(SeekBar seekBar) {
|
| 1405 | 1406 |
|
| 1407 |
processVideo(true); |
|
| 1406 | 1408 |
} |
| 1407 | 1409 |
}); |
| 1408 | 1410 |
|
| ... | ... | |
| 1420 | 1422 |
@Override |
| 1421 | 1423 |
public void onStopTrackingTouch(SeekBar seekBar) {
|
| 1422 | 1424 |
|
| 1425 |
processVideo(true); |
|
| 1423 | 1426 |
} |
| 1424 | 1427 |
}); |
| 1425 | 1428 |
|
| ... | ... | |
| 1688 | 1691 |
|
| 1689 | 1692 |
} |
| 1690 | 1693 |
|
| 1691 |
@Override
|
|
| 1694 |
/**
|
|
| 1692 | 1695 |
public void onItemClick(QuickAction source, int pos, int actionId) {
|
| 1693 | 1696 |
|
| 1694 | 1697 |
switch (actionId) {
|
| ... | ... | |
| 1742 | 1745 |
updateRegionDisplay(mediaPlayer.getCurrentPosition()); |
| 1743 | 1746 |
|
| 1744 | 1747 |
} |
| 1745 |
|
|
| 1748 |
**/ |
|
| 1746 | 1749 |
|
| 1747 | 1750 |
/* |
| 1748 | 1751 |
* Actual deletion of original |
| app/src/main/res/layout/videoeditor.xml | ||
|---|---|---|
| 49 | 49 |
android:secondaryProgress="0" |
| 50 | 50 |
android:progressDrawable="@android:drawable/progress_horizontal" |
| 51 | 51 |
/> |
| 52 |
|
|
| 52 |
<ProgressBar |
|
| 53 |
android:layout_width="wrap_content" |
|
| 54 |
android:layout_height="match_parent" |
|
| 55 |
android:id="@+id/progress_spinner" |
|
| 56 |
android:visibility="gone" |
|
| 57 |
/> |
|
| 53 | 58 |
|
| 54 | 59 |
</LinearLayout> |
| 55 | 60 |
|
| ... | ... | |
| 58 | 63 |
android:layout_height="wrap_content" |
| 59 | 64 |
android:orientation="horizontal" |
| 60 | 65 |
> |
| 61 |
<!-- |
|
| 62 |
<Button |
|
| 63 |
android:id="@+id/button_auto" |
|
| 64 |
android:layout_width="wrap_content" |
|
| 65 |
android:layout_height="match_parent" |
|
| 66 |
android:text="Auto-Detect" |
|
| 67 |
/>--> |
|
| 68 | 66 |
|
| 69 | 67 |
<TextView |
| 70 |
android:layout_width="wrap_content"
|
|
| 68 |
android:layout_width="60dp"
|
|
| 71 | 69 |
android:layout_height="match_parent" |
| 72 | 70 |
android:text="Pixelize:" |
| 73 | 71 |
android:gravity="center_vertical|right" |
| 74 | 72 |
/> |
| 75 | 73 |
<SeekBar |
| 76 | 74 |
android:id="@+id/seekbar_video_obscure" |
| 77 |
android:layout_width="80dp"
|
|
| 75 |
android:layout_width="120dp"
|
|
| 78 | 76 |
android:layout_height="match_parent" |
| 79 | 77 |
android:max="128" |
| 80 | 78 |
|
| 81 | 79 |
/> |
| 82 | 80 |
<TextView |
| 83 |
android:layout_width="wrap_content"
|
|
| 81 |
android:layout_width="60dp"
|
|
| 84 | 82 |
android:layout_height="match_parent" |
| 85 | 83 |
android:text="Distort:" |
| 86 | 84 |
android:gravity="center_vertical|right" |
| 87 | 85 |
/> |
| 88 | 86 |
<SeekBar |
| 89 | 87 |
android:id="@+id/seekbar_audio_obscure" |
| 90 |
android:layout_width="80dp"
|
|
| 88 |
android:layout_width="120dp"
|
|
| 91 | 89 |
android:layout_height="match_parent" |
| 92 | 90 |
android:max="64" |
| 93 | 91 |
|
| 94 | 92 |
/> |
| 95 |
<Button |
|
| 96 |
android:id="@+id/button_preview" |
|
| 97 |
android:layout_width="wrap_content" |
|
| 98 |
android:layout_height="match_parent" |
|
| 99 |
android:text="Preview" |
|
| 100 |
/> |
|
| 93 |
|
|
| 94 |
|
|
| 95 |
</LinearLayout> |
|
| 96 |
<!-- |
|
| 97 |
<LinearLayout |
|
| 98 |
android:layout_width="match_parent" |
|
| 99 |
android:layout_height="wrap_content" |
|
| 100 |
android:orientation="horizontal" |
|
| 101 |
> |
|
| 102 |
|
|
| 103 |
<TextView |
|
| 104 |
android:layout_width="60dp" |
|
| 105 |
android:layout_height="match_parent" |
|
| 106 |
android:text="Brighten:" |
|
| 107 |
android:gravity="center_vertical|right" |
|
| 108 |
/> |
|
| 109 |
<SeekBar |
|
| 110 |
android:id="@+id/seekbar_video_brightness" |
|
| 111 |
android:layout_width="120dp" |
|
| 112 |
android:layout_height="match_parent" |
|
| 113 |
android:max="128" |
|
| 114 |
|
|
| 115 |
/> |
|
| 116 |
<TextView |
|
| 117 |
android:layout_width="60dp" |
|
| 118 |
android:layout_height="match_parent" |
|
| 119 |
android:text="Saturate:" |
|
| 120 |
android:gravity="center_vertical|right" |
|
| 121 |
/> |
|
| 122 |
<SeekBar |
|
| 123 |
android:id="@+id/seekbar_video_saturate" |
|
| 124 |
android:layout_width="120dp" |
|
| 125 |
android:layout_height="match_parent" |
|
| 126 |
android:max="64" |
|
| 127 |
|
|
| 128 |
/> |
|
| 129 |
|
|
| 101 | 130 |
|
| 102 | 131 |
</LinearLayout> |
| 132 |
--> |
|
| 103 | 133 |
</LinearLayout> |
| 104 | 134 |
|
| 105 | 135 |
|
| app/src/main/res/values/strings.xml | ||
|---|---|---|
| 142 | 142 |
<string name="video_remote_trail">Remove Trail</string> |
| 143 | 143 |
<string name="do_tweet">Do Tween</string> |
| 144 | 144 |
<string name="video_remove_keyframe">Remove Keyframe</string> |
| 145 |
<string name="processing">Processing...</string> |
|
| 145 | 146 |
|
| 146 | 147 |
</resources> |
| app/src/main/res/values/styles.xml | ||
|---|---|---|
| 27 | 27 |
<style name="Animations" /> |
| 28 | 28 |
|
| 29 | 29 |
<!-- PopDownMenu --> |
| 30 |
<!-- |
|
| 31 |
|
|
| 30 | 32 |
<style name="Animations.PopDownMenu" /> |
| 31 | 33 |
|
| 32 | 34 |
<style name="Animations.PopDownMenu.Left"> |
| ... | ... | |
| 43 | 45 |
<item name="@android:windowEnterAnimation">@anim/grow_from_top</item> |
| 44 | 46 |
<item name="@android:windowExitAnimation">@anim/shrink_from_bottom</item> |
| 45 | 47 |
</style> |
| 46 |
|
|
| 48 |
--> |
|
| 49 |
|
|
| 47 | 50 |
<!-- PopUpMenu --> |
| 51 |
<!-- |
|
| 48 | 52 |
<style name="Animations.PopUpMenu" /> |
| 49 | 53 |
|
| 50 | 54 |
<style name="Animations.PopUpMenu.Left"> |
| ... | ... | |
| 61 | 65 |
<item name="@android:windowEnterAnimation">@anim/grow_from_bottom</item> |
| 62 | 66 |
<item name="@android:windowExitAnimation">@anim/shrink_from_top</item> |
| 63 | 67 |
</style> |
| 64 |
|
|
| 68 |
--> |
|
| 69 |
|
|
| 65 | 70 |
<style name="CustomTheme"> |
| 66 | 71 |
<item name="android:windowNoTitle">true</item> |
| 67 | 72 |
<item name="android:paddingTop">10px</item> |
Also available in: Unified diff