add theme selector dark/light
This commit is contained in:
parent
cfd172ce62
commit
36a9c467c7
24 changed files with 398 additions and 273 deletions
|
|
@ -15,7 +15,5 @@ public class ApplicationTest extends ApplicationTestCase<Application> {
|
|||
}
|
||||
|
||||
public void testFFT() {
|
||||
short[] buf = RawSamples.generateSound(16000, 4500, 100);
|
||||
short[] fft = RawSamples.fft(buf, 0, buf.length);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppThemeLight">
|
||||
<service android:name=".services.RecordingService" />
|
||||
<activity
|
||||
android:name=".activities.SettingsActivity"
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
android:name=".activities.MainActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
android:theme="@style/AppThemeLight.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import android.view.MenuInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
|
||||
/**
|
||||
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
|
|
@ -22,6 +24,7 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
|||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(((MainApplication) getApplication()).getUserTheme());
|
||||
getDelegate().installViewFactory();
|
||||
getDelegate().onCreate(savedInstanceState);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
|
|||
|
|
@ -435,6 +435,9 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setTheme(((MainApplication) getApplication()).getMainTheme());
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||
|
|
|
|||
|
|
@ -147,6 +147,9 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setTheme(((MainApplication) getApplication()).getUserTheme());
|
||||
|
||||
setContentView(R.layout.activity_recording);
|
||||
|
||||
pitch = (PitchView) findViewById(R.id.recording_pitch);
|
||||
|
|
@ -273,9 +276,7 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
pitch.clear(cut / samplesUpdate);
|
||||
for (int i = 0; i < len; i += samplesUpdate) {
|
||||
double dB = RawSamples.getDB(buf, i, samplesUpdate);
|
||||
short[] ss = new short[samplesUpdate];
|
||||
System.arraycopy(buf, i, ss, 0, ss.length);
|
||||
pitch.add(dB, ss);
|
||||
pitch.add(dB);
|
||||
}
|
||||
updateSamples(samplesTime);
|
||||
}
|
||||
|
|
@ -615,12 +616,10 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
|
||||
for (int i = 0; i < readSize; i += samplesUpdate) {
|
||||
final double dB = RawSamples.getDB(buffer, i, samplesUpdate);
|
||||
final short[] ss = new short[samplesUpdate];
|
||||
System.arraycopy(buffer, i, ss, 0, ss.length);
|
||||
handle.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pitch.add(dB, ss);
|
||||
pitch.add(dB);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.annotation.TargetApi;
|
|||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.media.Ringtone;
|
||||
|
|
@ -23,6 +24,7 @@ import android.support.v4.app.ActivityCompat;
|
|||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.axet.audiorecorder.R;
|
||||
|
|
@ -41,7 +43,7 @@ import java.util.List;
|
|||
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
|
||||
* API Guide</a> for more information on developing a Settings UI.
|
||||
*/
|
||||
public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
public class SettingsActivity extends AppCompatPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
/**
|
||||
* A preference value change listener that updates the preference's summary
|
||||
* to reflect its new value.
|
||||
|
|
@ -120,8 +122,12 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setupActionBar();
|
||||
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
shared.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, new GeneralPreferenceFragment()).commit();
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +201,23 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if(key.equals(MainApplication.PREFERENCE_THEME)) {
|
||||
finish();
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
shared.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows general preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
|
|
@ -226,6 +249,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||
}
|
||||
|
||||
bindPreferenceSummaryToValue(findPreference(MainApplication.PREFERENCE_RATE));
|
||||
bindPreferenceSummaryToValue(findPreference(MainApplication.PREFERENCE_THEME));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
package com.github.axet.audiorecorder.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.TypedArray;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import com.github.axet.androidlibrary.widgets.ThemeUtils;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
|
||||
public class MainApplication extends Application {
|
||||
|
|
@ -13,12 +18,37 @@ public class MainApplication extends Application {
|
|||
public static final String PREFERENCE_SILENT = "silence";
|
||||
public static final String PREFERENCE_ENCODING = "encoding";
|
||||
public static final String PREFERENCE_LAST = "last_recording";
|
||||
public static final String PREFERENCE_THEME = "theme";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
PreferenceManager.setDefaultValues(this, R.xml.pref_general, false);
|
||||
|
||||
Context context = this;
|
||||
context.setTheme(getUserTheme());
|
||||
Log.d("123", "color " + Integer.toHexString(ThemeUtils.getThemeColor(context, android.R.attr.textColorSecondary)));
|
||||
}
|
||||
|
||||
public int getUserTheme() {
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String theme = shared.getString(MainApplication.PREFERENCE_THEME, "");
|
||||
if (theme.equals("Theme_Dark")) {
|
||||
return R.style.AppThemeDark;
|
||||
} else {
|
||||
return R.style.AppThemeLight;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMainTheme() {
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String theme = shared.getString(MainApplication.PREFERENCE_THEME, "");
|
||||
if (theme.equals("Theme_Dark")) {
|
||||
return R.style.AppThemeDark_NoActionBar;
|
||||
} else {
|
||||
return R.style.AppThemeLight_NoActionBar;
|
||||
}
|
||||
}
|
||||
|
||||
static public String formatTime(int tt) {
|
||||
|
|
|
|||
|
|
@ -143,43 +143,7 @@ public class RawSamples {
|
|||
|
||||
public static double getDB(double amplitude) {
|
||||
// https://en.wikipedia.org/wiki/Sound_pressure
|
||||
return 20.0 * Math.log10(amplitude / 32768d);
|
||||
}
|
||||
|
||||
public static short[] generateSound(int sampleRate, int freqHz, int durationMs) {
|
||||
int count = sampleRate * durationMs / 1000;
|
||||
short[] samples = new short[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
short sample = (short) (Math.sin(2 * Math.PI * i / (sampleRate / freqHz)) * 0x7FFF);
|
||||
samples[i] = sample;
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
public static short[] fft(short[] buffer, int offset, int len) {
|
||||
int len2 = (int) Math.pow(2, Math.ceil(Math.log(len) / Math.log(2)));
|
||||
|
||||
final double[][] dataRI = new double[][]{
|
||||
new double[len2], new double[len2]
|
||||
};
|
||||
|
||||
double[] dataR = dataRI[0];
|
||||
double[] dataI = dataRI[1];
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
dataR[i] = buffer[offset + i];
|
||||
}
|
||||
|
||||
FastFourierTransformer.transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD);
|
||||
|
||||
short[] data = new short[len2 / 2];
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Complex c = new Complex(dataR[i], dataI[i]);
|
||||
data[i] = (short) (2.0 / len * c.abs());
|
||||
}
|
||||
|
||||
return data;
|
||||
return 20.0 * Math.log10(amplitude / 0x7FFF);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import android.app.PendingIntent;
|
|||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
|
|
@ -16,6 +19,7 @@ import android.widget.RemoteViews;
|
|||
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.activities.RecordingActivity;
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
|
||||
/**
|
||||
* RecordingActivity more likly to be removed from memory when paused then service. Notification button
|
||||
|
|
@ -140,6 +144,19 @@ public class RecordingService extends Service {
|
|||
view.setOnClickPendingIntent(R.id.notification_pause, pe);
|
||||
view.setImageViewResource(R.id.notification_pause, !recording ? R.drawable.play : R.drawable.pause);
|
||||
|
||||
getBaseContext().setTheme(((MainApplication) getApplication()).getUserTheme());
|
||||
|
||||
view.apply(new ContextWrapper(getBaseContext()) {
|
||||
public Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException {
|
||||
return new ContextWrapper(getBaseContext().createPackageContext(packageName, flags)) {
|
||||
@Override
|
||||
public Resources.Theme getTheme() {
|
||||
return getBaseContext().getTheme();
|
||||
}
|
||||
};
|
||||
}
|
||||
}, null);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
|
||||
.setOngoing(true)
|
||||
.setContentTitle("Recording")
|
||||
|
|
|
|||
|
|
@ -11,21 +11,13 @@ import android.view.View;
|
|||
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
public class FFTBarView extends View {
|
||||
public class FFTBarView extends FFTView {
|
||||
public static final String TAG = FFTBarView.class.getSimpleName();
|
||||
|
||||
Paint paint;
|
||||
short[] buffer;
|
||||
|
||||
int barCount;
|
||||
float barWidth;
|
||||
float barDeli;
|
||||
|
||||
int max;
|
||||
|
||||
Paint textPaint;
|
||||
Rect textBounds;
|
||||
|
||||
public FFTBarView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
|
@ -41,46 +33,11 @@ public class FFTBarView extends View {
|
|||
}
|
||||
|
||||
void create() {
|
||||
paint = new Paint();
|
||||
paint.setColor(0xff0433AE);
|
||||
paint.setStrokeWidth(dp2px(1));
|
||||
|
||||
textBounds = new Rect();
|
||||
|
||||
textPaint = new Paint();
|
||||
textPaint.setColor(Color.GRAY);
|
||||
textPaint.setAntiAlias(true);
|
||||
textPaint.setTextSize(20f);
|
||||
|
||||
if (isInEditMode()) {
|
||||
//buffer = simple();
|
||||
buffer = RawSamples.generateSound(16000, 4000, 100);
|
||||
buffer = RawSamples.fft(buffer, 0, buffer.length);
|
||||
}
|
||||
super.create();
|
||||
}
|
||||
|
||||
public void setBuffer(short[] buf) {
|
||||
buffer = RawSamples.fft(buf, 0, buf.length);
|
||||
|
||||
max = Integer.MIN_VALUE;
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
max = Math.max(buffer[i], max);
|
||||
}
|
||||
}
|
||||
|
||||
short[] simple() {
|
||||
int sampleRate = 1000;
|
||||
int count = sampleRate;
|
||||
short[] samples = new short[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
double x = i / (double) sampleRate;
|
||||
double y = 0;
|
||||
y += 0.9 * Math.sin(50 * 2 * Math.PI * x);
|
||||
y += 0.5 * Math.sin(80 * 2 * Math.PI * x);
|
||||
y += 0.7 * Math.sin(40 * 2 * Math.PI * x);
|
||||
samples[i] = (short) (y / 2.1 * 0x7fff);
|
||||
}
|
||||
return samples;
|
||||
public void setBuffer(double[] buf) {
|
||||
super.setBuffer(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -113,10 +70,6 @@ public class FFTBarView extends View {
|
|||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
}
|
||||
|
||||
int dp2px(float dp) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
if (barCount == 0)
|
||||
|
|
@ -134,7 +87,7 @@ public class FFTBarView extends View {
|
|||
int offset = i * step;
|
||||
int end = Math.min(offset + step, buffer.length);
|
||||
for (int k = offset; k < end; k++) {
|
||||
short s = buffer[k];
|
||||
double s = buffer[k];
|
||||
max = Math.max(max, s);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,9 @@ import android.view.View;
|
|||
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
public class FFTChartView extends View {
|
||||
public class FFTChartView extends FFTView {
|
||||
public static final String TAG = FFTChartView.class.getSimpleName();
|
||||
|
||||
Paint paint;
|
||||
short[] buffer;
|
||||
|
||||
Paint textPaint;
|
||||
Rect textBounds;
|
||||
|
||||
public FFTChartView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
|
@ -37,42 +31,13 @@ public class FFTChartView extends View {
|
|||
}
|
||||
|
||||
void create() {
|
||||
paint = new Paint();
|
||||
paint.setColor(0xff0433AE);
|
||||
paint.setStrokeWidth(dp2px(1));
|
||||
|
||||
textBounds = new Rect();
|
||||
|
||||
textPaint = new Paint();
|
||||
textPaint.setColor(Color.GRAY);
|
||||
textPaint.setAntiAlias(true);
|
||||
textPaint.setTextSize(20f);
|
||||
|
||||
if (isInEditMode()) {
|
||||
buffer = simple();
|
||||
//buffer = RawSamples.generateSound(16000, 4000, 100);
|
||||
//buffer = RawSamples.fft(buffer, 0, buffer.length);
|
||||
}
|
||||
super.create();
|
||||
}
|
||||
|
||||
public void setBuffer(short[] buf) {
|
||||
buffer = RawSamples.fft(buf, 0, buf.length);
|
||||
public void setBuffer(double[] buf) {
|
||||
super.setBuffer(buf);
|
||||
}
|
||||
|
||||
short[] simple() {
|
||||
int sampleRate = 1000;
|
||||
int count = sampleRate;
|
||||
short[] samples = new short[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
double x = i / (double) sampleRate;
|
||||
double y = 0;
|
||||
y += 0.9 * Math.sin(50 * 2 * Math.PI * x);
|
||||
y += 0.5 * Math.sin(80 * 2 * Math.PI * x);
|
||||
y += 0.7 * Math.sin(40 * 2 * Math.PI * x);
|
||||
samples[i] = (short) (y / 2.1 * 0x7fff);
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
|
|
@ -83,33 +48,34 @@ public class FFTChartView extends View {
|
|||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
}
|
||||
|
||||
int dp2px(float dp) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
int max = Integer.MIN_VALUE;
|
||||
if (buffer == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
min = Math.min(buffer[i], min);
|
||||
max = Math.max(buffer[i], max);
|
||||
}
|
||||
canvas.drawColor(Color.RED);
|
||||
|
||||
int h = getHeight();
|
||||
|
||||
if (min < 0) {
|
||||
h = h / 2;
|
||||
}
|
||||
|
||||
float startX = 0, startY = h;
|
||||
|
||||
float step = canvas.getWidth() / (float) buffer.length;
|
||||
int w = getWidth() - getPaddingLeft() - getPaddingRight();
|
||||
|
||||
float step = w / (float) buffer.length;
|
||||
|
||||
double min = Integer.MAX_VALUE;
|
||||
double max = Integer.MIN_VALUE;
|
||||
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
double v = buffer[i];
|
||||
|
||||
min = Math.min(v, min);
|
||||
max = Math.max(v, max);
|
||||
|
||||
v = (RawSamples.MAXIMUM_DB + v) / RawSamples.MAXIMUM_DB;
|
||||
|
||||
float endX = startX;
|
||||
float endY = h - h * (buffer[i] / (float) 0x7fff);
|
||||
float endY = (float) (h - h * v);
|
||||
|
||||
canvas.drawLine(startX, startY, endX, endY, paint);
|
||||
|
||||
|
|
@ -122,7 +88,7 @@ public class FFTChartView extends View {
|
|||
|
||||
String tMax = "" + max;
|
||||
textPaint.getTextBounds(tMax, 0, tMax.length(), textBounds);
|
||||
canvas.drawText("" + max, getWidth() - textBounds.width(), getHeight(), textPaint);
|
||||
canvas.drawText("" + max, w - textBounds.width(), getHeight(), textPaint);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,151 @@
|
|||
package com.github.axet.audiorecorder.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
import org.apache.commons.math3.complex.Complex;
|
||||
import org.apache.commons.math3.transform.DftNormalization;
|
||||
import org.apache.commons.math3.transform.FastFourierTransformer;
|
||||
import org.apache.commons.math3.transform.TransformType;
|
||||
|
||||
public class FFTView extends View {
|
||||
public static final String TAG = FFTView.class.getSimpleName();
|
||||
|
||||
Paint paint;
|
||||
double[] buffer;
|
||||
|
||||
Paint textPaint;
|
||||
Rect textBounds;
|
||||
|
||||
public FFTView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public FFTView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public FFTView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
create();
|
||||
}
|
||||
|
||||
void create() {
|
||||
paint = new Paint();
|
||||
paint.setColor(0xff0433AE);
|
||||
paint.setStrokeWidth(dp2px(1));
|
||||
|
||||
textBounds = new Rect();
|
||||
|
||||
textPaint = new Paint();
|
||||
textPaint.setColor(Color.GRAY);
|
||||
textPaint.setAntiAlias(true);
|
||||
textPaint.setTextSize(20f);
|
||||
|
||||
if (isInEditMode()) {
|
||||
short[] b = simple();
|
||||
b = generateSound(16000, 4000, 100);
|
||||
buffer = fft(b, 0, b.length);
|
||||
//buffer = RawSamples.generateSound(16000, 4000, 100);
|
||||
//buffer = RawSamples.fft(buffer, 0, buffer.length);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBuffer(double[] buf) {
|
||||
buffer = buf;
|
||||
}
|
||||
|
||||
public static short[] generateSound(int sampleRate, int freqHz, int durationMs) {
|
||||
int count = sampleRate * durationMs / 1000;
|
||||
short[] samples = new short[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
short sample = (short) (Math.sin(2 * Math.PI * i / (sampleRate / freqHz)) * 0x7FFF);
|
||||
samples[i] = sample;
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
public static double[] asDouble(short[] buffer, int offset, int len) {
|
||||
double[] dd = new double[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
dd[i] = buffer[offset + i] / (float) 0x7fff;
|
||||
}
|
||||
return dd;
|
||||
}
|
||||
|
||||
public static double[] fft(short[] buffer, int offset, int len) {
|
||||
int len2 = (int) Math.pow(2, Math.ceil(Math.log(len) / Math.log(2)));
|
||||
|
||||
final double[][] dataRI = new double[][]{
|
||||
new double[len2], new double[len2]
|
||||
};
|
||||
|
||||
double[] dataR = dataRI[0];
|
||||
double[] dataI = dataRI[1];
|
||||
|
||||
double powerInput = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
dataR[i] = buffer[offset + i] / (float) 0x7fff;
|
||||
powerInput += dataR[i] * dataR[i];
|
||||
}
|
||||
powerInput = Math.sqrt(powerInput / len);
|
||||
|
||||
FastFourierTransformer.transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD);
|
||||
|
||||
double[] data = new double[len2 / 2];
|
||||
|
||||
data[0] = 10 * Math.log10(Math.pow(new Complex(dataR[0], dataI[0]).abs() / len2, 2));
|
||||
|
||||
double powerOutput = 0;
|
||||
for (int i = 1; i < data.length; i++) {
|
||||
Complex c = new Complex(dataR[i], dataI[i]);
|
||||
double p = c.abs();
|
||||
p = p / len2;
|
||||
p = p * p;
|
||||
p = p * 2;
|
||||
double dB = 10 * Math.log10(p);
|
||||
|
||||
powerOutput += p;
|
||||
data[i] = dB;
|
||||
}
|
||||
powerOutput = Math.sqrt(powerOutput);
|
||||
|
||||
// if(powerInput != powerOutput) {
|
||||
// throw new RuntimeException("in " + powerInput + " out " + powerOutput);
|
||||
// }
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static short[] simple() {
|
||||
int sampleRate = 1000;
|
||||
int count = sampleRate;
|
||||
short[] samples = new short[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
double x = i / (double) count;
|
||||
double y = 0;
|
||||
//y += 0.6 * Math.sin(20 * 2 * Math.PI * x);
|
||||
//y += 0.4 * Math.sin(50 * 2 * Math.PI * x);
|
||||
//y += 0.2 * Math.sin(80 * 2 * Math.PI * x);
|
||||
y += Math.sin(100 * 2 * Math.PI * x);
|
||||
y += Math.sin(200 * 2 * Math.PI * x);
|
||||
y += Math.sin(300 * 2 * Math.PI * x);
|
||||
// max = 2.2;
|
||||
samples[i] = (short) (y / 3 * 0x7fff);
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
int dp2px(float dp) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.github.axet.audiorecorder.widgets;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
|
|
@ -15,6 +16,9 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.axet.androidlibrary.widgets.ThemeUtils;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
|
@ -39,10 +43,7 @@ public class PitchView extends ViewGroup {
|
|||
// in other words how many milliseconds do we need to show whole pitch.
|
||||
int pitchTime;
|
||||
|
||||
Paint paint;
|
||||
Paint paintRed;
|
||||
List<Double> data = new LinkedList<>();
|
||||
List<short[]> dataSamples = new LinkedList<>();
|
||||
|
||||
// how many pitches we can fit on screen
|
||||
int pitchScreenCount;
|
||||
|
|
@ -56,7 +57,6 @@ public class PitchView extends ViewGroup {
|
|||
int pitchSize;
|
||||
|
||||
PitchGraphView graph;
|
||||
FFTBarView fft;
|
||||
PitchCurrentView current;
|
||||
|
||||
long time = 0;
|
||||
|
|
@ -77,9 +77,6 @@ public class PitchView extends ViewGroup {
|
|||
|
||||
Handler handler;
|
||||
|
||||
int pitchColor = 0xff0433AE;
|
||||
Paint cutColor = new Paint();
|
||||
|
||||
public static class HandlerUpdate implements Runnable {
|
||||
long start;
|
||||
long updateSpeed;
|
||||
|
|
@ -123,8 +120,11 @@ public class PitchView extends ViewGroup {
|
|||
}
|
||||
|
||||
public class PitchGraphView extends View {
|
||||
Paint paint;
|
||||
Paint paintRed;
|
||||
Paint editPaint;
|
||||
Paint playPaint;
|
||||
Paint cutColor;
|
||||
|
||||
public PitchGraphView(Context context) {
|
||||
this(context, null);
|
||||
|
|
@ -137,12 +137,24 @@ public class PitchView extends ViewGroup {
|
|||
public PitchGraphView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
paint = new Paint();
|
||||
paint.setColor(getThemeColor(R.attr.colorPrimary));
|
||||
paint.setStrokeWidth(pitchWidth);
|
||||
|
||||
paintRed = new Paint();
|
||||
paintRed.setColor(Color.RED);
|
||||
paintRed.setStrokeWidth(pitchWidth);
|
||||
|
||||
cutColor = new Paint();
|
||||
cutColor.setColor(getThemeColor(android.R.attr.textColorHint));
|
||||
cutColor.setStrokeWidth(pitchWidth);
|
||||
|
||||
editPaint = new Paint();
|
||||
editPaint.setColor(Color.BLACK);
|
||||
editPaint.setColor(getThemeColor(R.attr.colorPrimaryDark));
|
||||
editPaint.setStrokeWidth(pitchWidth);
|
||||
|
||||
playPaint = new Paint();
|
||||
playPaint.setColor(Color.BLUE);
|
||||
playPaint.setColor(getThemeColor(R.attr.colorPrimaryDark));
|
||||
playPaint.setStrokeWidth(pitchWidth / 2);
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +282,7 @@ public class PitchView extends ViewGroup {
|
|||
textPaint.setTextSize(20f);
|
||||
|
||||
paint = new Paint();
|
||||
paint.setColor(pitchColor);
|
||||
paint.setColor(getThemeColor(R.attr.colorPrimary));
|
||||
paint.setStrokeWidth(pitchWidth);
|
||||
}
|
||||
|
||||
|
|
@ -309,6 +321,10 @@ public class PitchView extends ViewGroup {
|
|||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
if (data.size() > 0) {
|
||||
current.update(getEnd());
|
||||
}
|
||||
|
||||
float y = getPaddingTop() + textBounds.height();
|
||||
|
||||
int x = getWidth() / 2 - textBounds.width() / 2;
|
||||
|
|
@ -351,15 +367,24 @@ public class PitchView extends ViewGroup {
|
|||
|
||||
pitchTime = pitchSize * UPDATE_SPEED;
|
||||
|
||||
// bg = getThemeColor(android.R.attr.windowBackground);
|
||||
cutColor.setColor(0xff0443BE); // getThemeColor(android.R.attr.textColorPrimaryDisableOnly));
|
||||
|
||||
graph = new PitchGraphView(getContext());
|
||||
addView(graph);
|
||||
|
||||
fft = new FFTBarView(getContext());
|
||||
fft.setPadding(0, dp2px(2), 0, 0);
|
||||
addView(fft);
|
||||
// fft = new FFTChartView(getContext()) {
|
||||
// @Override
|
||||
// public void onDraw(Canvas canvas) {
|
||||
// if (data.size() > 0) {
|
||||
// short[] buf = dataSamples.get(getEnd());
|
||||
// double[] d = FFTView.fft(buf, 0, buf.length);
|
||||
// //double[] d = asDouble(buf, 0, buf.length);
|
||||
// fft.setBuffer(d);
|
||||
// }
|
||||
//
|
||||
// super.onDraw(canvas);
|
||||
// }
|
||||
// };
|
||||
// fft.setPadding(0, dp2px(2), 0, 0);
|
||||
// addView(fft);
|
||||
|
||||
current = new PitchCurrentView(getContext());
|
||||
current.setPadding(0, dp2px(2), 0, 0);
|
||||
|
|
@ -367,23 +392,17 @@ public class PitchView extends ViewGroup {
|
|||
|
||||
if (isInEditMode()) {
|
||||
for (int i = 0; i < 3000; i++) {
|
||||
data.add(-Math.random() * RawSamples.MAXIMUM_DB);
|
||||
short[] buf = new short[1600];
|
||||
dataSamples.add(buf);
|
||||
data.add(-Math.sin(i) * RawSamples.MAXIMUM_DB);
|
||||
}
|
||||
}
|
||||
|
||||
paint = new Paint();
|
||||
paint.setColor(0xff0433AE);
|
||||
paint.setStrokeWidth(pitchWidth);
|
||||
|
||||
paintRed = new Paint();
|
||||
paintRed.setColor(Color.RED);
|
||||
paintRed.setStrokeWidth(pitchWidth);
|
||||
|
||||
time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public int getThemeColor(int id) {
|
||||
return ThemeUtils.getThemeColor(getContext(), id);
|
||||
}
|
||||
|
||||
public int getMaxPitchCount(int width) {
|
||||
int pitchScreenCount = width / pitchSize + 1;
|
||||
|
||||
|
|
@ -405,7 +424,6 @@ public class PitchView extends ViewGroup {
|
|||
if (data.size() > max) {
|
||||
int cut = data.size() - max;
|
||||
data.subList(0, cut).clear();
|
||||
dataSamples.subList(0, cut).clear();
|
||||
samples += cut;
|
||||
|
||||
int m = data.size() - 1;
|
||||
|
|
@ -417,9 +435,8 @@ public class PitchView extends ViewGroup {
|
|||
}
|
||||
}
|
||||
|
||||
public void add(double a, short[] ss) {
|
||||
public void add(double a) {
|
||||
data.add(a);
|
||||
dataSamples.add(ss);
|
||||
}
|
||||
|
||||
public void drawCalc() {
|
||||
|
|
@ -472,15 +489,6 @@ public class PitchView extends ViewGroup {
|
|||
|
||||
public void draw() {
|
||||
graph.invalidate();
|
||||
|
||||
if (data.size() > 0) {
|
||||
fft.setBuffer(dataSamples.get(getEnd()));
|
||||
}
|
||||
fft.invalidate();
|
||||
|
||||
if (data.size() > 0) {
|
||||
current.update(getEnd());
|
||||
}
|
||||
current.invalidate();
|
||||
}
|
||||
|
||||
|
|
@ -488,51 +496,35 @@ public class PitchView extends ViewGroup {
|
|||
return pitchTime;
|
||||
}
|
||||
|
||||
int getThemeColor(int id) {
|
||||
TypedValue typedValue = new TypedValue();
|
||||
Context context = getContext();
|
||||
Resources.Theme theme = context.getTheme();
|
||||
if (theme.resolveAttribute(id, typedValue, true)) {
|
||||
if (Build.VERSION.SDK_INT >= 23)
|
||||
return context.getResources().getColor(typedValue.resourceId, theme);
|
||||
else
|
||||
return context.getResources().getColor(typedValue.resourceId);
|
||||
} else {
|
||||
return Color.TRANSPARENT;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
current.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
int ww = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
|
||||
int hh = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
|
||||
|
||||
fft.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp2px(20), MeasureSpec.getMode(widthMeasureSpec)));
|
||||
current.measure(MeasureSpec.makeMeasureSpec(ww, MeasureSpec.AT_MOST),
|
||||
MeasureSpec.makeMeasureSpec(hh, MeasureSpec.AT_MOST));
|
||||
|
||||
int hh = MeasureSpec.getSize(heightMeasureSpec) - current.getMeasuredHeight() - fft.getMeasuredHeight();
|
||||
graph.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(hh, MeasureSpec.getMode(widthMeasureSpec)));
|
||||
hh = hh - current.getMeasuredHeight();
|
||||
|
||||
graph.measure(MeasureSpec.makeMeasureSpec(ww, MeasureSpec.AT_MOST),
|
||||
MeasureSpec.makeMeasureSpec(hh, MeasureSpec.AT_MOST));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
graph.layout(0, 0, graph.getMeasuredWidth(), graph.getMeasuredHeight());
|
||||
fft.layout(0, graph.getMeasuredHeight(), fft.getMeasuredWidth(),
|
||||
graph.getMeasuredHeight() + fft.getMeasuredHeight());
|
||||
current.layout(0, fft.getBottom(), current.getMeasuredWidth(),
|
||||
fft.getBottom() + current.getMeasuredHeight());
|
||||
graph.layout(getPaddingLeft(), getPaddingTop(),
|
||||
getPaddingLeft() + graph.getMeasuredWidth(), getPaddingTop() + graph.getMeasuredHeight());
|
||||
|
||||
current.layout(getPaddingLeft(), graph.getBottom(),
|
||||
getPaddingLeft() + current.getMeasuredWidth(), graph.getBottom() + current.getMeasuredHeight());
|
||||
}
|
||||
|
||||
int dp2px(float dp) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
graph.draw(canvas);
|
||||
current.draw(canvas);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (edit != null)
|
||||
HandlerUpdate.stop(handler, edit);
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="@color/colorAccent" />
|
||||
|
||||
</shape>
|
||||
|
|
@ -10,14 +10,14 @@
|
|||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
android:theme="@style/AppThemeLight.AppBarOverlay">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
app:popupTheme="@style/AppThemeLight.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
android:id="@+id/recording_pitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:layout_centerInParent="true" />
|
||||
android:layout_centerInParent="true"
|
||||
android:padding="5dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -51,28 +52,24 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<ImageButton
|
||||
<com.github.axet.androidlibrary.widgets.RoundButton
|
||||
android:id="@+id/recording_cut"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/round"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_content_cut_24dp"
|
||||
android:text="Cancel" />
|
||||
|
||||
<ImageButton
|
||||
<com.github.axet.androidlibrary.widgets.RoundButton
|
||||
android:id="@+id/recording_play"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/round"
|
||||
android:src="@drawable/play" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
<com.github.axet.androidlibrary.widgets.RoundButton
|
||||
android:id="@+id/recording_edit_done"
|
||||
style="Widget.AppCompat.RoundButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/round"
|
||||
android:src="@drawable/ic_close_24dp" />
|
||||
</com.github.axet.androidlibrary.widgets.EqualLinearLayout>
|
||||
</FrameLayout>
|
||||
|
|
@ -96,28 +93,24 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
<com.github.axet.androidlibrary.widgets.RoundButton
|
||||
android:id="@+id/recording_cancel"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/round"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_close_24dp"
|
||||
android:text="Cancel" />
|
||||
|
||||
<ImageButton
|
||||
<com.github.axet.androidlibrary.widgets.RoundButton
|
||||
android:id="@+id/recording_pause"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/round"
|
||||
android:src="@drawable/ic_pause_24dp" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
<com.github.axet.androidlibrary.widgets.RoundButton
|
||||
android:id="@+id/recording_done"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/round"
|
||||
android:src="@drawable/ic_done" />
|
||||
|
||||
</com.github.axet.androidlibrary.widgets.EqualLinearLayout>
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
android:id="@+id/status_bar_latest_event_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:background="@android:color/white">
|
||||
android:background="?android:windowBackground">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/notification_large_icon_width"
|
||||
android:layout_height="@dimen/notification_large_icon_height"
|
||||
android:src="@drawable/ic_mic_24dp"
|
||||
android:tint="@android:color/black" />
|
||||
android:tint="?android:attr/colorForeground" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/notification_main_column"
|
||||
|
|
@ -30,18 +30,17 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/notification_title"
|
||||
style="@style/AlertDialog.AppCompat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Audio Recorder"
|
||||
android:textColor="@android:color/black" />
|
||||
android:textColor="?android:attr/colorForeground" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Audio Recorder"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textColor="?android:attr/textColorHint"
|
||||
android:textSize="@dimen/notification_subtext_size" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@
|
|||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="#dedede"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/secondBackground"
|
||||
android:padding="5dp">
|
||||
|
||||
<LinearLayout
|
||||
|
|
@ -81,6 +81,7 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:id="@+id/recording_player_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -113,21 +114,21 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/play"
|
||||
android:tint="@color/colorAccent" />
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/recording_player_share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/share"
|
||||
android:tint="@color/colorAccent" />
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/recording_player_trash"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/trash"
|
||||
android:tint="@color/colorAccent" />
|
||||
android:tint="?attr/colorAccent" />
|
||||
</com.github.axet.androidlibrary.widgets.EqualLinearLayout>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
<resources>>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<resources>
|
||||
<style name="AppThemeLight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
<style name="AppThemeDark.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
|
|
|
|||
4
app/src/main/res/values/attrs.xml
Normal file
4
app/src/main/res/values/attrs.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="secondBackground" format="color" />
|
||||
</resources>
|
||||
|
|
@ -2,6 +2,4 @@
|
|||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
<color name="button_bg">#606060</color>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -21,16 +21,26 @@
|
|||
<item>8000</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings" >
|
||||
<string-array name="encodings">
|
||||
<item>.wav (default)</item>
|
||||
<item>.m4a</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings_values" >
|
||||
<string-array name="encodings_values">
|
||||
<item>wav</item>
|
||||
<item>m4a</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="themes">
|
||||
<item>Theme White (default)</item>
|
||||
<item>Theme Dark</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="themes_values">
|
||||
<item>Theme_White</item>
|
||||
<item>Theme_Dark</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_activity_main">Audio Recorder</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,31 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<style name="AppThemeLight" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorAccent">#FF4081</item>
|
||||
<item name="secondBackground">#c2c2c2</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<style name="AppThemeLight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
<style name="AppThemeLight.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
<style name="AppThemeLight.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
<style name="AppThemeDark" parent="Theme.AppCompat">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">#a4a4a4</item>
|
||||
<item name="secondBackground">#5a595b</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<com.github.axet.androidlibrary.widgets.StoragePathPreference
|
||||
android:defaultValue="Audio Recorder"
|
||||
android:key="storage_path"
|
||||
|
|
@ -37,4 +38,14 @@
|
|||
android:summary="Put phone in 'silence mode' during recording"
|
||||
android:title="Silence mode" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="Theme_White"
|
||||
android:entries="@array/themes"
|
||||
android:entryValues="@array/themes_values"
|
||||
android:key="theme"
|
||||
android:negativeButtonText="@null"
|
||||
android:positiveButtonText="@null"
|
||||
android:summary="Set application theme (dark / light)"
|
||||
android:title="Application Theme" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue