阅读界面添加电量显示
This commit is contained in:
1 parent
d08598ab71
commit
6e97c23dda
9 files changed
+365
-34
No files matched your search
+1
-1
@@ -1,2 +1,2 @@
|
||||
APP_ABI := all
|
||||
APP_ABI := armeabi armeabi-v7a x86
|
||||
APP_PLATFORM := android-14
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
static int errorCode;
|
||||
|
||||
// TODO is GIF87a work fine ?
|
||||
|
||||
static inline freeSafely(void* p) {
|
||||
if (p != NULL) free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return NULL if error
|
||||
*/
|
||||
@@ -66,7 +72,7 @@ static int streamReadFun(GifFileType* gif, GifByteType* bytes, int size) {
|
||||
/*
|
||||
* stack store the index to draw
|
||||
* stack capacity should be imageCount * sizeof(int).
|
||||
* When read it, use for(; size > 0; size--).
|
||||
* When read it, use from tail to head
|
||||
*/
|
||||
static void getDrawStack(GIF* gif, int targetIndex, int* which, int* stack,
|
||||
int* stackSize) {
|
||||
@@ -313,7 +319,7 @@ static void render(GIF* gif, int index) {
|
||||
int height = gif->gifFile->SHeight;
|
||||
int imageCount = gif->gifFile->ImageCount;
|
||||
int which, stackSize;
|
||||
int* stack = (int*) malloc(imageCount * sizeof(int));
|
||||
int stack[imageCount];
|
||||
void* tempPoint;
|
||||
int tempInt;
|
||||
|
||||
@@ -346,9 +352,6 @@ static void render(GIF* gif, int index) {
|
||||
glTexSubImage2D(DEFAULT_TARGET, 0, 0, 0, width,
|
||||
height, gif->format, DEFAULT_TYPE, gif->pixels);
|
||||
|
||||
// release
|
||||
free(stack);
|
||||
|
||||
// update pxlIndex
|
||||
gif->pxlIndex = index;
|
||||
|
||||
@@ -372,8 +375,10 @@ static void render(GIF* gif, int index) {
|
||||
}
|
||||
if (gif->bak == NULL)
|
||||
gif->bak = malloc(size);
|
||||
memcpy(gif->bak, gif->pixels, size);
|
||||
gif->bakIndex = index;
|
||||
if (gif->bak != NULL) {
|
||||
memcpy(gif->bak, gif->pixels, size);
|
||||
gif->bakIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,6 +393,9 @@ static GIF* analysisGifFileType(GifFileType* gifFile, int format, int* delays) {
|
||||
int imageCount = gifFile->ImageCount;
|
||||
|
||||
gif = (GIF*) malloc(sizeof(GIF));
|
||||
if (gif == NULL)
|
||||
return NULL;
|
||||
|
||||
gif->gifFile = gifFile;
|
||||
gif->trans = (int*) malloc(imageCount * sizeof(int));
|
||||
gif->disposals = (int*) malloc(imageCount * sizeof(int));
|
||||
@@ -410,6 +418,14 @@ static GIF* analysisGifFileType(GifFileType* gifFile, int format, int* delays) {
|
||||
gif->bak = NULL;
|
||||
gif->bakIndex = -1;
|
||||
|
||||
if (gif->trans == NULL || gif->disposals == NULL || gif->pixels == NULL) {
|
||||
freeSafely(gif->pixels);
|
||||
freeSafely(gif->disposals);
|
||||
freeSafely(gif->trans);
|
||||
free(gif);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
trans = gif->trans;
|
||||
disposals = gif->disposals;
|
||||
for (i = 0; i < imageCount; i++) {
|
||||
@@ -471,15 +487,19 @@ jobject GIF_DecodeStream(JNIEnv* env, jobject is, jint format) {
|
||||
// Check image count
|
||||
imageCount = gifFile->ImageCount;
|
||||
if (imageCount < 1) {
|
||||
DGifCloseFile(gif->gifFile, &errorCode);
|
||||
DGifCloseFile(gifFile, &errorCode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get GIF
|
||||
delays = (int*) malloc(imageCount * sizeof(int));
|
||||
if (delays == NULL) {
|
||||
DGifCloseFile(gifFile, &errorCode);
|
||||
return NULL;
|
||||
}
|
||||
gif = analysisGifFileType(gifFile, format, delays);
|
||||
if (gif == NULL) {
|
||||
DGifCloseFile(gif->gifFile, &errorCode);
|
||||
DGifCloseFile(gifFile, &errorCode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -512,10 +532,10 @@ void GIF_Free(JNIEnv* env, int nativeImage) {
|
||||
|
||||
GIF* gif = (GIF*) nativeImage;
|
||||
DGifCloseFile(gif->gifFile, &errorCode);
|
||||
if (gif->trans != NULL) free(gif->trans);
|
||||
if (gif->disposals != NULL) free(gif->disposals);
|
||||
if (gif->pixels != NULL) free(gif->pixels);
|
||||
if (gif->bak != NULL) free(gif->bak);
|
||||
freeSafely(gif->trans);
|
||||
freeSafely(gif->disposals);
|
||||
freeSafely(gif->pixels);
|
||||
freeSafely(gif->bak);
|
||||
free(gif);
|
||||
}
|
||||
|
||||
+2
-4
@@ -52,15 +52,13 @@ Java_com_hippo_ehviewer_gallery_image_Image_nativeFree(JNIEnv* env,
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_ehviewer_gallery_image_Image_nativeRender(JNIEnv* env,
|
||||
jclass clazz, jint target, jint level, jint xoffset, jint yoffset,
|
||||
jint format, jint type, jint nativeImage, jint fileFormat) {
|
||||
jclass clazz, jint format, jint type, jint nativeImage, jint fileFormat) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_ehviewer_gallery_image_GifImage_nativeRender(JNIEnv* env,
|
||||
jclass clazz, jint target, jint level, jint xoffset, jint yoffset,
|
||||
jint format, jint type, jint nativeImage, jint fileFormat, jint index) {
|
||||
jclass clazz, jint format, jint type, jint nativeImage, jint fileFormat, jint index) {
|
||||
|
||||
if (type != DEFAULT_TYPE || fileFormat != FORMAT_GIF)
|
||||
return;
|
||||
|
||||
@@ -34,6 +34,17 @@
|
||||
android:layout_marginRight="12dp"
|
||||
android:textColor="@color/secondary_text_light" />
|
||||
|
||||
<com.hippo.ehviewer.widget.BatteryView
|
||||
xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/battery"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:textColor="@color/secondary_text_light"
|
||||
auto:bvColor="@color/secondary_text_light" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/action_bar"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -89,5 +89,9 @@
|
||||
<attr name="mpThickness" format="dimension" />
|
||||
<attr name="mpInnerRadius" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<declare-styleable name="BatteryView">
|
||||
<attr name="bvColor" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.drawable;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class BatteryDrawable extends Drawable {
|
||||
|
||||
private static final String TAG = BatteryDrawable.class.getSimpleName();
|
||||
|
||||
public static final int WARN_LIMIT = 15;
|
||||
|
||||
private int mColor = Color.WHITE;
|
||||
private int mWarnColor = Color.RED;
|
||||
private int mElect = -1;
|
||||
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
|
||||
|
||||
public BatteryDrawable() {
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mElect == -1)
|
||||
return;
|
||||
|
||||
Rect bounds = getBounds();
|
||||
int width = bounds.width();
|
||||
int height = bounds.height();
|
||||
int strokeWidth = (int)(Math.sqrt(width * width + height * height) * 0.06f);
|
||||
int halfStrokeWidth = strokeWidth / 2;
|
||||
int turn1 = width * 6 / 7;
|
||||
int turn2 = height / 3;
|
||||
int start = strokeWidth;
|
||||
int stop = turn1 - halfStrokeWidth;
|
||||
int levelEnd = start + (stop - start) * mElect / 100;
|
||||
|
||||
float[] drawPoints = {
|
||||
halfStrokeWidth, 0 + strokeWidth, halfStrokeWidth, height - strokeWidth,
|
||||
0, halfStrokeWidth, turn1 - halfStrokeWidth, halfStrokeWidth,
|
||||
0, height - halfStrokeWidth, turn1 - halfStrokeWidth, height - halfStrokeWidth,
|
||||
turn1, 0, turn1, turn2 - halfStrokeWidth,
|
||||
turn1, height, turn1, height - turn2 + halfStrokeWidth,
|
||||
turn1 - halfStrokeWidth, turn2, width, turn2,
|
||||
turn1 - halfStrokeWidth, height - turn2, width, height - turn2,
|
||||
width - halfStrokeWidth, turn2 + halfStrokeWidth, width - halfStrokeWidth, height - turn2 - halfStrokeWidth};
|
||||
|
||||
mPaint.setStrokeWidth(strokeWidth);
|
||||
canvas.drawLines(drawPoints, mPaint);
|
||||
canvas.drawRect(start, 0 + strokeWidth, levelEnd, height - strokeWidth, mPaint);
|
||||
}
|
||||
|
||||
private boolean isWarn() {
|
||||
return mElect <= WARN_LIMIT;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
if (mColor == color)
|
||||
return;
|
||||
|
||||
mColor = color;
|
||||
if (!isWarn()) {
|
||||
mPaint.setColor(mColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setWarnColor(int color) {
|
||||
if (mWarnColor == color)
|
||||
return;
|
||||
|
||||
mWarnColor = color;
|
||||
if (isWarn()) {
|
||||
mPaint.setColor(mWarnColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setElect(int elect) {
|
||||
if (mElect == elect)
|
||||
return;
|
||||
|
||||
mElect = elect;
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
public void setElect(int elect, boolean warn) {
|
||||
if (mElect == elect)
|
||||
return;
|
||||
|
||||
mElect = elect;
|
||||
updatePaint(warn);
|
||||
}
|
||||
|
||||
private void updatePaint() {
|
||||
updatePaint(isWarn());
|
||||
}
|
||||
|
||||
private void updatePaint(boolean warn) {
|
||||
if (warn)
|
||||
mPaint.setColor(mWarnColor);
|
||||
else
|
||||
mPaint.setColor(mColor);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.hippo.ehviewer.gallery.image;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
|
||||
public class GifImage extends Image {
|
||||
|
||||
@@ -25,7 +24,7 @@ public class GifImage extends Image {
|
||||
private final int mImageCount;
|
||||
private final int[] mDelayArray;
|
||||
private long mDelaySum;
|
||||
private final long mStartTime;
|
||||
private long mStartTime;
|
||||
|
||||
private int mLastIndex = -1;
|
||||
|
||||
@@ -38,15 +37,19 @@ public class GifImage extends Image {
|
||||
mDelaySum = 0;
|
||||
for (int delay : delayArray)
|
||||
mDelaySum += delay;
|
||||
mStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private int getCurIndex() {
|
||||
long curTime = System.currentTimeMillis();
|
||||
long time = (curTime - mStartTime) % mDelaySum;
|
||||
int end = mImageCount - 1;
|
||||
int index = 0;
|
||||
for (; index < end && (time -= mDelayArray[index]) > 0; index++);
|
||||
if (mLastIndex == -1) {
|
||||
index = 0;
|
||||
mStartTime = System.currentTimeMillis();
|
||||
} else {
|
||||
long curTime = System.currentTimeMillis();
|
||||
long time = (curTime - mStartTime) % mDelaySum;
|
||||
int end = mImageCount - 1;
|
||||
for (; index < end && (time -= mDelayArray[index]) > 0; index++);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -60,7 +63,7 @@ public class GifImage extends Image {
|
||||
if (mNativeImage != 0) {
|
||||
int index = getCurIndex();
|
||||
if (mLastIndex != index) {
|
||||
nativeRender(GL11.GL_TEXTURE_2D, 0, 0, 0, mFormat, mType, mNativeImage, FORMAT_GIF, index);
|
||||
nativeRender(mFormat, mType, mNativeImage, FORMAT_GIF, index);
|
||||
mLastIndex = index;
|
||||
}
|
||||
}
|
||||
@@ -70,6 +73,5 @@ public class GifImage extends Image {
|
||||
System.loadLibrary("image");
|
||||
}
|
||||
|
||||
private static native void nativeRender(int target, int level, int xoffset,
|
||||
int yoffset, int format, int type, int nativeImage, int fileFormat, int index);
|
||||
private static native void nativeRender(int format, int type, int nativeImage, int fileFormat, int index);
|
||||
}
|
||||
@@ -18,8 +18,6 @@ package com.hippo.ehviewer.gallery.image;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
|
||||
|
||||
public class Image {
|
||||
|
||||
@@ -74,8 +72,7 @@ public class Image {
|
||||
|
||||
public void render() {
|
||||
if (mNativeImage != 0) {
|
||||
nativeRender(GL11.GL_TEXTURE_2D, 0, 0, 0,
|
||||
mFormat, mType, mNativeImage, mFileFormat);
|
||||
nativeRender(mFormat, mType, mNativeImage, mFileFormat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,5 +105,5 @@ public class Image {
|
||||
|
||||
private static native Image nativeDecodeStream(InputStream is, int format);
|
||||
private static native void nativeFree(int mNativeImage, int format);
|
||||
private static native void nativeRender(int target, int level, int xoffset, int yoffset, int format, int type, int nativeImage, int fileFormat);
|
||||
private static native void nativeRender(int format, int type, int nativeImage, int fileFormat);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.drawable.BatteryDrawable;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
|
||||
public class BatteryView extends TextView {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = BatteryView.class.getSimpleName();
|
||||
|
||||
private int mLevel = 0;
|
||||
private boolean mCharging = false;
|
||||
|
||||
private BatteryDrawable mDrawable;
|
||||
|
||||
private boolean mAttached = false;
|
||||
private boolean mIsChargerWorking = false;
|
||||
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
|
||||
* 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||
boolean charging = (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||
== BatteryManager.BATTERY_STATUS_CHARGING);
|
||||
|
||||
if (mLevel != level || mCharging != charging) {
|
||||
mLevel = level;
|
||||
mCharging = charging;
|
||||
if (mCharging && mLevel != 100) {
|
||||
startCharger();
|
||||
} else {
|
||||
stopCharger();
|
||||
mDrawable.setElect(mLevel);
|
||||
}
|
||||
setText(String.valueOf(mLevel) + "%");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCharger = new Runnable() {
|
||||
|
||||
private int level = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
level += 5;
|
||||
if (level > mLevel)
|
||||
level = 0;
|
||||
mDrawable.setElect(level, mLevel <= BatteryDrawable.WARN_LIMIT);
|
||||
getHandler().postDelayed(mCharger, 500);
|
||||
}
|
||||
};
|
||||
|
||||
public BatteryView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public BatteryView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BatteryView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
init();
|
||||
|
||||
TypedArray typedArray = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.BatteryView, defStyleAttr, 0);
|
||||
int color = typedArray.getColor(R.styleable.BatteryView_bvColor, Color.WHITE);
|
||||
typedArray.recycle();
|
||||
|
||||
mDrawable.setColor(color);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mDrawable = new BatteryDrawable();
|
||||
// TODO how to get size ?
|
||||
int height = Ui.dp2pix(12);
|
||||
mDrawable.setBounds(0, 0, (int) (height / 0.618f), height);
|
||||
setCompoundDrawables(mDrawable, null, null, null);
|
||||
setCompoundDrawablePadding(Ui.dp2pix(5));
|
||||
}
|
||||
|
||||
private void startCharger() {
|
||||
if (!mIsChargerWorking) {
|
||||
getHandler().post(mCharger);
|
||||
mIsChargerWorking = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopCharger() {
|
||||
if (mIsChargerWorking) {
|
||||
getHandler().removeCallbacks(mCharger);
|
||||
mIsChargerWorking = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
if (!mAttached) {
|
||||
mAttached = true;
|
||||
|
||||
registerReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
if (mAttached) {
|
||||
unregisterReceiver();
|
||||
stopCharger();
|
||||
mAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReceiver() {
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
|
||||
}
|
||||
|
||||
private void unregisterReceiver() {
|
||||
getContext().unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user