Demo 工程迁移到 APIJSON-Demo 项目;APIJSONORM 和 APIJSONFramework 迁移到最外层;调整文档中的链接

This commit is contained in:
TommyLemon 2020-09-15 22:12:10 +08:00
parent aa45fc0304
commit 91255dab8b
698 changed files with 68 additions and 65507 deletions

View File

@ -1,7 +0,0 @@
*.iml
.gradle
/local.properties
.idea
.DS_Store
/build
/captures

View File

@ -1 +0,0 @@
/build

View File

@ -1,25 +0,0 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion '29.0.0'
defaultConfig {
minSdkVersion 20
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
}

View File

@ -1,17 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/Tommy/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -1,13 +0,0 @@
package com.ericssonlabs;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ericssonlabs"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<!-- 复制粘贴到你的工程的AndroidManifest.xml内对应位置 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -->
<!-- 需要的权限和功能 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<!-- 需要的权限和功能 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<!-- 复制粘贴到你的工程的AndroidManifest.xml内对应位置 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
</manifest>

View File

@ -1,243 +0,0 @@
package com.zxing.activity;
import java.io.IOException;
import java.util.Vector;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.Window;
import android.widget.Toast;
import com.ericssonlabs.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.zxing.camera.CameraManager;
import com.zxing.decoding.CaptureActivityHandler;
import com.zxing.decoding.CaptureActivityHandler.DecodeCallback;
import com.zxing.decoding.InactivityTimer;
import com.zxing.view.ViewfinderView;
/**
* Initial the camera
* @author Ryan.Tang
* @modifier Lemon
* @use extends CaptureActivity并且在setContentView方法后调用init方法
*/
public abstract class CaptureActivity extends Activity implements Callback, DecodeCallback {
// private static final String TAG = "CaptureActivity";
protected Activity context;
protected SurfaceView surfaceView;
protected ViewfinderView viewfinderView;
/**初始化必须在setContentView之后
* @param context
* @param viewfinderView
*/
protected void init(Activity context, SurfaceView surfaceView, ViewfinderView viewfinderView) {
this.context = context;
this.surfaceView = surfaceView;
this.viewfinderView = viewfinderView;
CameraManager.init(getApplication());
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
}
private boolean isOn = false;
protected final boolean isOn() {
return isOn;
}
/**打开或关闭闪关灯
* @param open
*/
protected void switchLight(boolean on) {
if (on == isOn()) {
return;
}
isOn = CameraManager.get().switchLight(on);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
private CaptureActivityHandler handler;
private boolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.10f;
private boolean vibrate;
@Override
protected void onResume() {
super.onResume();
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null;
playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true;
}
@Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
isOn = false;
CameraManager.get().closeDriver();
}
@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
public static final String RESULT_QRCODE_STRING = "RESULT_QRCODE_STRING";
/**
* Handler scan result
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
//FIXME
if (resultString.equals("")) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}
setResult(RESULT_OK, new Intent().putExtra(RESULT_QRCODE_STRING, resultString));
finish();
}
private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet, viewfinderView, this);
}
}
@Override
public void drawViewfinder() {
viewfinderView.drawViewfinder();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public Handler getHandler() {
return handler;
}
private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);
AssetFileDescriptor file = getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
private static final long VIBRATE_DURATION = 200L;
private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
}
/**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.camera;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class AutoFocusCallback implements Camera.AutoFocusCallback {
private static final String TAG = AutoFocusCallback.class.getSimpleName();
private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
private Handler autoFocusHandler;
private int autoFocusMessage;
void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
this.autoFocusHandler = autoFocusHandler;
this.autoFocusMessage = autoFocusMessage;
}
public void onAutoFocus(boolean success, Camera camera) {
if (autoFocusHandler != null) {
Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
autoFocusHandler = null;
} else {
Log.d(TAG, "Got auto-focus callback, but no handler for it");
}
}
}

View File

@ -1,280 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.camera;
import java.util.regex.Pattern;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
final class CameraConfigurationManager {
private static final String TAG = CameraConfigurationManager.class.getSimpleName();
private static final int TEN_DESIRED_ZOOM = 27;
private static final int DESIRED_SHARPNESS = 30;
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private final Context context;
private Point screenResolution;
private Point cameraResolution;
private int previewFormat;
private String previewFormatString;
CameraConfigurationManager(Context context) {
this.context = context;
}
/**
* Reads, one time, values from the camera that are needed by the app.
*/
void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
previewFormat = parameters.getPreviewFormat();
previewFormatString = parameters.get("preview-format");
Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = new Point(display.getWidth(), display.getHeight());
Log.d(TAG, "Screen resolution: " + screenResolution);
// //Lemon add 扫描框修改,解决拉伸但导致成像模糊识别率很低<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Point screenResolutionForCamera = new Point();
// screenResolutionForCamera.x = screenResolution.x;
// screenResolutionForCamera.y = screenResolution.y;
// // preview size is always something like 480*320, other 320*480
// if (screenResolution.x < screenResolution.y) {
// screenResolutionForCamera.x = screenResolution.y;
// screenResolutionForCamera.y = screenResolution.x;
// }
//Lemon add 扫描框修改,解决拉伸>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Lemon 扫描框修改,解决拉伸但导致成像模糊识别率很低 screenResolution改为screenResolutionForCamera);<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
cameraResolution = getCameraResolution(parameters, screenResolution);
Log.d(TAG, "Camera resolution: " + screenResolution);
//Lemon 扫描框修改,解决拉伸但导致成像模糊识别率很低 screenResolution改为screenResolutionForCamera);>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
/**
* Sets the camera up to take preview images which are used for both preview and decoding.
* We detect the preview format here so that buildLuminanceSource() can build an appropriate
* LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
* and the planar Y can be used for barcode scanning without a copy in some cases.
*/
void setDesiredCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Log.d(TAG, "Setting preview size: " + cameraResolution);
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
setFlash(parameters);
setZoom(parameters);
//setSharpness(parameters);
//modify here
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
Point getCameraResolution() {
return cameraResolution;
}
Point getScreenResolution() {
return screenResolution;
}
int getPreviewFormat() {
return previewFormat;
}
String getPreviewFormatString() {
return previewFormatString;
}
private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
// saw this on Xperia
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
}
if (cameraResolution == null) {
// Ensure that the camera resolution is a multiple of 8, as the screen may not be.
cameraResolution = new Point(
(screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
previewSize = previewSize.trim();
int dimPosition = previewSize.indexOf('x');
if (dimPosition < 0) {
Log.w(TAG, "Bad preview-size: " + previewSize);
continue;
}
int newX;
int newY;
try {
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad preview-size: " + previewSize);
continue;
}
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
if (newDiff == 0) {
bestX = newX;
bestY = newY;
break;
} else if (newDiff < diff) {
bestX = newX;
bestY = newY;
diff = newDiff;
}
}
if (bestX > 0 && bestY > 0) {
return new Point(bestX, bestY);
}
return null;
}
private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
int tenBestValue = 0;
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
stringValue = stringValue.trim();
double value;
try {
value = Double.parseDouble(stringValue);
} catch (NumberFormatException nfe) {
return tenDesiredZoom;
}
int tenValue = (int) (10.0 * value);
if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
tenBestValue = tenValue;
}
}
return tenBestValue;
}
private void setFlash(Camera.Parameters parameters) {
// FIXME: This is a hack to turn the flash off on the Samsung Galaxy.
// And this is a hack-hack to work around a different value on the Behold II
// Restrict Behold II check to Cupcake, per Samsung's advice
//if (Build.MODEL.contains("Behold II") &&
// CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {
if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
parameters.set("flash-value", 1);
} else {
parameters.set("flash-value", 2);
}
// This is the standard setting to turn the flash off that all devices should honor.
parameters.set("flash-mode", "off");
}
private void setZoom(Camera.Parameters parameters) {
String zoomSupportedString = parameters.get("zoom-supported");
if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
return;
}
int tenDesiredZoom = TEN_DESIRED_ZOOM;
String maxZoomString = parameters.get("max-zoom");
if (maxZoomString != null) {
try {
int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad max-zoom: " + maxZoomString);
}
}
String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
if (takingPictureZoomMaxString != null) {
try {
int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
}
}
String motZoomValuesString = parameters.get("mot-zoom-values");
if (motZoomValuesString != null) {
tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
}
String motZoomStepString = parameters.get("mot-zoom-step");
if (motZoomStepString != null) {
try {
double motZoomStep = Double.parseDouble(motZoomStepString.trim());
int tenZoomStep = (int) (10.0 * motZoomStep);
if (tenZoomStep > 1) {
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
}
} catch (NumberFormatException nfe) {
// continue
}
}
// Set zoom. This helps encourage the user to pull back.
// Some devices like the Behold have a zoom parameter
if (maxZoomString != null || motZoomValuesString != null) {
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
}
// Most devices, like the Hero, appear to expose this zoom parameter.
// It takes on values like "27" which appears to mean 2.7x zoom
if (takingPictureZoomMaxString != null) {
parameters.set("taking-picture-zoom", tenDesiredZoom);
}
}
public static int getDesiredSharpness() {
return DESIRED_SHARPNESS;
}
}

View File

@ -1,364 +0,0 @@
/*
* Copyright (C) 2008 ZXing authors
*
* 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.zxing.camera;
import java.io.IOException;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Build;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
/**
* This object wraps the Camera service object and expects to be the only one talking to it. The
* implementation encapsulates the steps needed to take preview-sized images, which are used for
* both preview and decoding.
*
*/
public final class CameraManager {
private static final String TAG = CameraManager.class.getSimpleName();
private static final int MIN_FRAME_WIDTH = 240;
private static final int MIN_FRAME_HEIGHT = 240;
private static final int MAX_FRAME_WIDTH = 480;
private static final int MAX_FRAME_HEIGHT = 360;
private static CameraManager cameraManager;
static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT
static {
int sdkInt;
try {
sdkInt = Integer.parseInt(Build.VERSION.SDK);
} catch (NumberFormatException nfe) {
// Just to be safe
sdkInt = 10000;
}
SDK_INT = sdkInt;
}
private final Context context;
private final CameraConfigurationManager configManager;
private Camera camera;
private Rect framingRect;
private Rect framingRectInPreview;
private boolean initialized;
private boolean previewing;
private final boolean useOneShotPreviewCallback;
/**
* Preview frames are delivered here, which we pass on to the registered handler. Make sure to
* clear the handler so it will only receive one message.
*/
private final PreviewCallback previewCallback;
/** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */
private final AutoFocusCallback autoFocusCallback;
/**
* Initializes this static object with the Context of the calling Activity.
*
* @param context The Activity which wants to use the camera.
*/
public static void init(Context context) {
if (cameraManager == null) {
cameraManager = new CameraManager(context);
}
}
/**
* Gets the CameraManager singleton instance.
*
* @return A reference to the CameraManager singleton.
*/
public static CameraManager get() {
return cameraManager;
}
private CameraManager(Context context) {
this.context = context;
this.configManager = new CameraConfigurationManager(context);
// Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older
// Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use
// the more efficient one shot callback, as the older one can swamp the system and cause it
// to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.
//useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;
useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake
previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
autoFocusCallback = new AutoFocusCallback();
}
/**
* Opens the camera driver and initializes the hardware parameters.
*
* @param holder The surface object which the camera will draw preview frames into.
* @throws IOException Indicates the camera driver failed to open.
*/
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
if (camera == null) {
throw new IOException();
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
//FIXME
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//<EFBFBD>Ƿ<EFBFBD>ʹ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>
// if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
// FlashlightManager.enableFlashlight();
// }
FlashlightManager.enableFlashlight();
}
}
//Lemon add <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private Parameters parameter;
/**开关闪光灯
* @param open
* @return
*/
public boolean switchLight(boolean open) {
parameter = camera.getParameters();
if (open) {
parameter.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameter);
return true;
} else {
parameter.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameter);
return false;
}
}
//Lemon add >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**
* Closes the camera driver if still in use.
*/
public void closeDriver() {
if (camera != null) {
FlashlightManager.disableFlashlight();
camera.release();
camera = null;
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
/**
* Tells the camera to stop drawing preview frames.
*/
public void stopPreview() {
if (camera != null && previewing) {
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
camera.stopPreview();
previewCallback.setHandler(null, 0);
autoFocusCallback.setHandler(null, 0);
previewing = false;
}
}
/**
* A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
* in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
* respectively.
*
* @param handler The handler to send the message to.
* @param message The what field of the message to be sent.
*/
public void requestPreviewFrame(Handler handler, int message) {
if (camera != null && previewing) {
previewCallback.setHandler(handler, message);
if (useOneShotPreviewCallback) {
camera.setOneShotPreviewCallback(previewCallback);
} else {
camera.setPreviewCallback(previewCallback);
}
}
}
/**
* Asks the camera hardware to perform an autofocus.
*
* @param handler The Handler to notify when the autofocus completes.
* @param message The message to deliver.
*/
public void requestAutoFocus(Handler handler, int message) {
if (camera != null && previewing) {
autoFocusCallback.setHandler(handler, message);
//Log.d(TAG, "Requesting auto-focus callback");
camera.autoFocus(autoFocusCallback);
}
}
/**
* Calculates the framing rect which the UI should draw to show the user where to place the
* barcode. This target helps with alignment as well as forces the user to hold the device
* far enough away to ensure the image will be in focus.
*
* @return The rectangle to draw on screen in window coordinates.
*/
public Rect getFramingRect() {
Point screenResolution = configManager.getScreenResolution();
if (framingRect == null) {
if (camera == null) {
return null;
}
//Lemon 扫描框修改,解决拉伸<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// int width = screenResolution.x * 3 / 4;
// if (width < MIN_FRAME_WIDTH) {
// width = MIN_FRAME_WIDTH;
// } else if (width > MAX_FRAME_WIDTH) {
// width = MAX_FRAME_WIDTH;
// }
// int height = screenResolution.y * 3 / 4;
// if (height < MIN_FRAME_HEIGHT) {
// height = MIN_FRAME_HEIGHT;
// } else if (height > MAX_FRAME_HEIGHT) {
// height = MAX_FRAME_HEIGHT;
// }
// int leftOffset = (screenResolution.x - width) / 2;
// int topOffset = (screenResolution.y - height) / 2;
// framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
// Log.d(TAG, "Calculated framing rect: " + framingRect);
//Lemon 扫描框修改,解决拉伸<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = (int) (metrics.widthPixels * 0.6);
int height = (int) (width * 0.9);
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 3;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width,
topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
//Lemon 扫描框修改,解决拉伸>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
return framingRect;
}
/**
* Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
* not UI / screen.
*/
public Rect getFramingRectInPreview() {
if (framingRectInPreview == null) {
Rect rect = new Rect(getFramingRect());
Point cameraResolution = configManager.getCameraResolution();
Point screenResolution = configManager.getScreenResolution();
//modify here
// rect.left = rect.left * cameraResolution.x / screenResolution.x;
// rect.right = rect.right * cameraResolution.x / screenResolution.x;
// rect.top = rect.top * cameraResolution.y / screenResolution.y;
// rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
framingRectInPreview = rect;
}
return framingRectInPreview;
}
/**
* Converts the result points from still resolution coordinates to screen coordinates.
*
* @param points The points returned by the Reader subclass through Result.getResultPoints().
* @return An array of Points scaled to the size of the framing rect and offset appropriately
* so they can be drawn in screen coordinates.
*/
/*
public Point[] convertResultPoints(ResultPoint[] points) {
Rect frame = getFramingRectInPreview();
int count = points.length;
Point[] output = new Point[count];
for (int x = 0; x < count; x++) {
output[x] = new Point();
output[x].x = frame.left + (int) (points[x].getX() + 0.5f);
output[x].y = frame.top + (int) (points[x].getY() + 0.5f);
}
return output;
}
*/
/**
* A factory method to build the appropriate LuminanceSource object based on the format
* of the preview buffers, as described by Camera.Parameters.
*
* @param data A preview frame.
* @param width The width of the image.
* @param height The height of the image.
* @return A PlanarYUVLuminanceSource instance.
*/
public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
Rect rect = getFramingRectInPreview();
int previewFormat = configManager.getPreviewFormat();
String previewFormatString = configManager.getPreviewFormatString();
switch (previewFormat) {
// This is the standard Android format which all devices are REQUIRED to support.
// In theory, it's the only one we should ever care about.
case PixelFormat.YCbCr_420_SP:
// This format has never been seen in the wild, but is compatible as we only care
// about the Y channel, so allow it.
case PixelFormat.YCbCr_422_SP:
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height());
default:
// The Samsung Work incorrectly uses this variant instead of the 'sp' version.
// Fortunately, it too has all the Y data up front, so we can read it.
if ("yuv420p".equals(previewFormatString)) {
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height());
}
}
throw new IllegalArgumentException("Unsupported picture format: " +
previewFormat + '/' + previewFormatString);
}
public Context getContext() {
return context;
}
}

View File

@ -1,150 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.camera;
import android.os.IBinder;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* This class is used to activate the weak light on some camera phones (not flash)
* in order to illuminate surfaces for scanning. There is no official way to do this,
* but, classes which allow access to this function still exist on some devices.
* This therefore proceeds through a great deal of reflection.
*
* See <a href="http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/">
* http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/</a> and
* <a href="http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java">
* http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java</a>.
* Thanks to Ryan Alford for pointing out the availability of this class.
*/
final class FlashlightManager {
private static final String TAG = FlashlightManager.class.getSimpleName();
private static final Object iHardwareService;
private static final Method setFlashEnabledMethod;
static {
iHardwareService = getHardwareService();
setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
if (iHardwareService == null) {
Log.v(TAG, "This device does supports control of a flashlight");
} else {
Log.v(TAG, "This device does not support control of a flashlight");
}
}
private FlashlightManager() {
}
/**
* 开启闪光灯
*/
//FIXME
static void enableFlashlight() {
setFlashlight(false);
}
static void disableFlashlight() {
setFlashlight(false);
}
private static Object getHardwareService() {
Class<?> serviceManagerClass = maybeForName("android.os.ServiceManager");
if (serviceManagerClass == null) {
return null;
}
Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
if (getServiceMethod == null) {
return null;
}
Object hardwareService = invoke(getServiceMethod, null, "hardware");
if (hardwareService == null) {
return null;
}
Class<?> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
if (iHardwareServiceStubClass == null) {
return null;
}
Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
if (asInterfaceMethod == null) {
return null;
}
return invoke(asInterfaceMethod, null, hardwareService);
}
private static Method getSetFlashEnabledMethod(Object iHardwareService) {
if (iHardwareService == null) {
return null;
}
Class<?> proxyClass = iHardwareService.getClass();
return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
}
private static Class<?> maybeForName(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException cnfe) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding class " + name, re);
return null;
}
}
private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {
try {
return clazz.getMethod(name, argClasses);
} catch (NoSuchMethodException nsme) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding method " + name, re);
return null;
}
}
private static Object invoke(Method method, Object instance, Object... args) {
try {
return method.invoke(instance, args);
} catch (IllegalAccessException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e);
return null;
} catch (InvocationTargetException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while invoking " + method, re);
return null;
}
}
private static void setFlashlight(boolean active) {
if (iHardwareService != null) {
invoke(setFlashEnabledMethod, iHardwareService, active);
}
}
}

View File

@ -1,133 +0,0 @@
/*
* Copyright 2009 ZXing authors
*
* 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.zxing.camera;
import com.google.zxing.LuminanceSource;
import android.graphics.Bitmap;
/**
* This object extends LuminanceSource around an array of YUV data returned from the camera driver,
* with the option to crop to a rectangle within the full data. This can be used to exclude
* superfluous pixels around the perimeter and speed up decoding.
*
* It works for any pixel format where the Y channel is planar and appears first, including
* YCbCr_420_SP and YCbCr_422_SP.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class PlanarYUVLuminanceSource extends LuminanceSource {
private final byte[] yuvData;
private final int dataWidth;
private final int dataHeight;
private final int left;
private final int top;
public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
int width, int height) {
super(width, height);
if (left + width > dataWidth || top + height > dataHeight) {
throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
}
this.yuvData = yuvData;
this.dataWidth = dataWidth;
this.dataHeight = dataHeight;
this.left = left;
this.top = top;
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
int offset = (y + top) * dataWidth + left;
System.arraycopy(yuvData, offset, row, 0, width);
return row;
}
@Override
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
// If the caller asks for the entire underlying image, save the copy and give them the
// original data. The docs specifically warn that result.length must be ignored.
if (width == dataWidth && height == dataHeight) {
return yuvData;
}
int area = width * height;
byte[] matrix = new byte[area];
int inputOffset = top * dataWidth + left;
// If the width matches the full width of the underlying data, perform a single copy.
if (width == dataWidth) {
System.arraycopy(yuvData, inputOffset, matrix, 0, area);
return matrix;
}
// Otherwise copy one cropped row at a time.
byte[] yuv = yuvData;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
inputOffset += dataWidth;
}
return matrix;
}
@Override
public boolean isCropSupported() {
return true;
}
public int getDataWidth() {
return dataWidth;
}
public int getDataHeight() {
return dataHeight;
}
public Bitmap renderCroppedGreyscaleBitmap() {
int width = getWidth();
int height = getHeight();
int[] pixels = new int[width * height];
byte[] yuv = yuvData;
int inputOffset = top * dataWidth + left;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
for (int x = 0; x < width; x++) {
int grey = yuv[inputOffset + x] & 0xff;
pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
}
inputOffset += dataWidth;
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.camera;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class PreviewCallback implements Camera.PreviewCallback {
private static final String TAG = PreviewCallback.class.getSimpleName();
private final CameraConfigurationManager configManager;
private final boolean useOneShotPreviewCallback;
private Handler previewHandler;
private int previewMessage;
PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
this.configManager = configManager;
this.useOneShotPreviewCallback = useOneShotPreviewCallback;
}
void setHandler(Handler previewHandler, int previewMessage) {
this.previewHandler = previewHandler;
this.previewMessage = previewMessage;
}
public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
if (previewHandler != null) {
Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
cameraResolution.y, data);
message.sendToTarget();
previewHandler = null;
} else {
Log.d(TAG, "Got preview callback, but no handler for it");
}
}
}

View File

@ -1,138 +0,0 @@
/*
* Copyright (C) 2008 ZXing authors
*
* 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.zxing.decoding;
import java.util.Vector;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.ericssonlabs.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.zxing.activity.CaptureActivity;
import com.zxing.camera.CameraManager;
import com.zxing.view.ViewfinderResultPointCallback;
import com.zxing.view.ViewfinderView;
/**
* This class handles all the messaging which comprises the state machine for capture.
*/
public final class CaptureActivityHandler extends Handler {
private static final String TAG = CaptureActivityHandler.class.getSimpleName();
public interface DecodeCallback {
void handleDecode(Result result, Bitmap barcode);
void drawViewfinder();
}
private State state;
private enum State {
PREVIEW,
SUCCESS,
DONE
}
private final Activity activity;
private final DecodeThread decodeThread;
private DecodeCallback decodeCallback;
public CaptureActivityHandler(CaptureActivity activity, Vector<BarcodeFormat> decodeFormats,
String characterSet, ViewfinderView viewfinderView, DecodeCallback decodeCallback) {
this.activity = activity;
this.decodeCallback = decodeCallback;
decodeThread = new DecodeThread(activity, decodeFormats, characterSet,
new ViewfinderResultPointCallback(viewfinderView));
decodeThread.start();
state = State.SUCCESS;
// Start ourselves capturing previews and decoding.
CameraManager.get().startPreview();
restartPreviewAndDecode();
}
@Override
public void handleMessage(Message message) {
if (message.what == R.id.auto_focus) {
//Log.d(TAG, "Got auto-focus message");
// When one auto focus pass finishes, start another. This is the closest thing to
// continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
if (state == State.PREVIEW) {
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
}
}else if (message.what == R.id.restart_preview) {
Log.d(TAG, "Got restart preview message");
restartPreviewAndDecode();
}else if (message.what == R.id.decode_succeeded) {
Log.d(TAG, "Got decode succeeded message");
state = State.SUCCESS;
Bundle bundle = message.getData();
/***********************************************************************/
Bitmap barcode = bundle == null ? null :
(Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);//<EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
decodeCallback.handleDecode((Result) message.obj, barcode);//<EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD>
/***********************************************************************/
}else if (message.what == R.id.decode_failed) {
// We're decoding as fast as possible, so when one decode fails, start another.
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
}else if (message.what == R.id.return_scan_result) {
Log.d(TAG, "Got return scan result message");
activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
activity.finish();
}else if (message.what == R.id.launch_product_query) {
Log.d(TAG, "Got product query message");
String url = (String) message.obj;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
activity.startActivity(intent);
}
}
public void quitSynchronously() {
state = State.DONE;
CameraManager.get().stopPreview();
Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
quit.sendToTarget();
try {
decodeThread.join();
} catch (InterruptedException e) {
// continue
}
// Be absolutely sure we don't send any queued up messages
removeMessages(R.id.decode_succeeded);
removeMessages(R.id.decode_failed);
}
private void restartPreviewAndDecode() {
if (state == State.SUCCESS) {
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
decodeCallback.drawViewfinder();
}
}
}

View File

@ -1,104 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.decoding;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;
import android.content.Intent;
import android.net.Uri;
import com.google.zxing.BarcodeFormat;
final class DecodeFormatManager {
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
static final Vector<BarcodeFormat> PRODUCT_FORMATS;
static final Vector<BarcodeFormat> ONE_D_FORMATS;
static final Vector<BarcodeFormat> QR_CODE_FORMATS;
static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;
static {
PRODUCT_FORMATS = new Vector<BarcodeFormat>(5);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
ONE_D_FORMATS = new Vector<BarcodeFormat>(PRODUCT_FORMATS.size() + 4);
ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
ONE_D_FORMATS.add(BarcodeFormat.CODE_39);
ONE_D_FORMATS.add(BarcodeFormat.CODE_93);
ONE_D_FORMATS.add(BarcodeFormat.CODE_128);
ONE_D_FORMATS.add(BarcodeFormat.ITF);
QR_CODE_FORMATS = new Vector<BarcodeFormat>(1);
QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);
DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
}
private DecodeFormatManager() {}
static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {
List<String> scanFormats = null;
String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);
if (scanFormatsString != null) {
scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));
}
return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));
}
static Vector<BarcodeFormat> parseDecodeFormats(Uri inputUri) {
List<String> formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);
if (formats != null && formats.size() == 1 && formats.get(0) != null){
formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));
}
return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));
}
private static Vector<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,
String decodeMode) {
if (scanFormats != null) {
Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
try {
for (String format : scanFormats) {
formats.add(BarcodeFormat.valueOf(format));
}
return formats;
} catch (IllegalArgumentException iae) {
// ignore it then
}
}
if (decodeMode != null) {
if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {
return PRODUCT_FORMATS;
}
if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {
return QR_CODE_FORMATS;
}
if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {
return DATA_MATRIX_FORMATS;
}
if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {
return ONE_D_FORMATS;
}
}
return null;
}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.decoding;
import java.util.Hashtable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.ericssonlabs.R;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.zxing.activity.CaptureActivity;
import com.zxing.camera.CameraManager;
import com.zxing.camera.PlanarYUVLuminanceSource;
final class DecodeHandler extends Handler {
private static final String TAG = DecodeHandler.class.getSimpleName();
private final CaptureActivity activity;
private final MultiFormatReader multiFormatReader;
DecodeHandler(CaptureActivity activity, Hashtable<DecodeHintType, Object> hints) {
multiFormatReader = new MultiFormatReader();
multiFormatReader.setHints(hints);
this.activity = activity;
}
@Override
public void handleMessage(Message message) {
if (message.what == R.id.decode) {
//Log.d(TAG, "Got decode message");
decode((byte[]) message.obj, message.arg1, message.arg2);
}else if (message.what == R.id.quit) {
Looper.myLooper().quit();
}
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
* reuse the same reader objects from one decode to the next.
*
* @param data The YUV preview frame.
* @param width The width of the preview frame.
* @param height The height of the preview frame.
*/
private void decode(byte[] data, int width, int height) {
long start = System.currentTimeMillis();
Result rawResult = null;
//modify here
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
int tmp = width; // Here we are swapping, that's the difference to #11
width = height;
height = tmp;
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
} catch (ReaderException re) {
// continue
} finally {
multiFormatReader.reset();
}
if (rawResult != null) {
long end = System.currentTimeMillis();
Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, rawResult);
Bundle bundle = new Bundle();
bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
message.setData(bundle);
//Log.d(TAG, "Sending decode succeeded message...");
message.sendToTarget();
} else {
Message message = Message.obtain(activity.getHandler(), R.id.decode_failed);
message.sendToTarget();
}
}
}

View File

@ -1,86 +0,0 @@
/*
* Copyright (C) 2008 ZXing authors
*
* 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.zxing.decoding;
import java.util.Hashtable;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import android.os.Handler;
import android.os.Looper;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ResultPointCallback;
import com.zxing.activity.CaptureActivity;
/**
* This thread does all the heavy lifting of decoding the images.
* 编码线程
*/
final class DecodeThread extends Thread {
public static final String BARCODE_BITMAP = "barcode_bitmap";
private final CaptureActivity activity;
private final Hashtable<DecodeHintType, Object> hints;
private Handler handler;
private final CountDownLatch handlerInitLatch;
DecodeThread(CaptureActivity activity,
Vector<BarcodeFormat> decodeFormats,
String characterSet,
ResultPointCallback resultPointCallback) {
this.activity = activity;
handlerInitLatch = new CountDownLatch(1);
hints = new Hashtable<DecodeHintType, Object>(3);
if (decodeFormats == null || decodeFormats.isEmpty()) {
decodeFormats = new Vector<BarcodeFormat>();
decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
}
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
if (characterSet != null) {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}
hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
}
Handler getHandler() {
try {
handlerInitLatch.await();
} catch (InterruptedException ie) {
// continue?
}
return handler;
}
@Override
public void run() {
Looper.prepare();
handler = new DecodeHandler(activity, hints);
handlerInitLatch.countDown();
Looper.loop();
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.decoding;
import android.app.Activity;
import android.content.DialogInterface;
/**
* Simple listener used to exit the app in a few cases.
*
*/
public final class FinishListener
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
private final Activity activityToFinish;
public FinishListener(Activity activityToFinish) {
this.activityToFinish = activityToFinish;
}
public void onCancel(DialogInterface dialogInterface) {
run();
}
public void onClick(DialogInterface dialogInterface, int i) {
run();
}
public void run() {
activityToFinish.finish();
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2010 ZXing authors
*
* 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.zxing.decoding;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
/**
* Finishes an activity after a period of inactivity.
*/
public final class InactivityTimer {
private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
private final ScheduledExecutorService inactivityTimer =
Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
private final Activity activity;
private ScheduledFuture<?> inactivityFuture = null;
public InactivityTimer(Activity activity) {
this.activity = activity;
onActivity();
}
public void onActivity() {
cancel();
inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
INACTIVITY_DELAY_SECONDS,
TimeUnit.SECONDS);
}
private void cancel() {
if (inactivityFuture != null) {
inactivityFuture.cancel(true);
inactivityFuture = null;
}
}
public void shutdown() {
cancel();
inactivityTimer.shutdown();
}
private static final class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
return thread;
}
}
}

View File

@ -1,190 +0,0 @@
/*
* Copyright (C) 2008 ZXing authors
*
* 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.zxing.decoding;
/**
* This class provides the constants to use when sending an Intent to Barcode Scanner.
* These strings are effectively API and cannot be changed.
*/
public final class Intents {
private Intents() {
}
public static final class Scan {
/**
* Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
* the results.
*/
public static final String ACTION = "com.google.zxing.client.android.SCAN";
/**
* By default, sending Scan.ACTION will decode all barcodes that we understand. However it
* may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
* one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).
* Optional.
*
* Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.
* It is overridden by that setting.
*/
public static final String MODE = "SCAN_MODE";
/**
* Comma-separated list of formats to scan for. The values must match the names of
* {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.
* Example: "EAN_13,EAN_8,QR_CODE"
*
* This overrides {@link #MODE}.
*/
public static final String SCAN_FORMATS = "SCAN_FORMATS";
/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
public static final String CHARACTER_SET = "CHARACTER_SET";
/**
* Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
* prices, reviews, etc. for products.
*/
public static final String PRODUCT_MODE = "PRODUCT_MODE";
/**
* Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
*/
public static final String ONE_D_MODE = "ONE_D_MODE";
/**
* Decode only QR codes.
*/
public static final String QR_CODE_MODE = "QR_CODE_MODE";
/**
* Decode only Data Matrix codes.
*/
public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE";
/**
* If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
* requested the scan via startSubActivity(). The barcodes contents can be retrieved with
* intent.getStringExtra(RESULT). If the user presses Back, the result code will be
* RESULT_CANCELED.
*/
public static final String RESULT = "SCAN_RESULT";
/**
* Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
* See Contents.Format for possible values.
*/
public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
/**
* Setting this to false will not save scanned codes in the history.
*/
public static final String SAVE_HISTORY = "SAVE_HISTORY";
private Scan() {
}
}
public static final class Encode {
/**
* Send this intent to encode a piece of data as a QR code and display it full screen, so
* that another person can scan the barcode from your screen.
*/
public static final String ACTION = "com.google.zxing.client.android.ENCODE";
/**
* The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
* Bundle, depending on the type and format specified. Non-QR Code formats should
* just use a String here. For QR Code, see Contents for details.
*/
public static final String DATA = "ENCODE_DATA";
/**
* The type of data being supplied if the format is QR Code. Use
* Intent.putExtra(TYPE, type) with one of Contents.Type.
*/
public static final String TYPE = "ENCODE_TYPE";
/**
* The barcode format to be displayed. If this isn't specified or is blank,
* it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where
* format is one of Contents.Format.
*/
public static final String FORMAT = "ENCODE_FORMAT";
private Encode() {
}
}
public static final class SearchBookContents {
/**
* Use Google Book Search to search the contents of the book provided.
*/
public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS";
/**
* The book to search, identified by ISBN number.
*/
public static final String ISBN = "ISBN";
/**
* An optional field which is the text to search for.
*/
public static final String QUERY = "QUERY";
private SearchBookContents() {
}
}
public static final class WifiConnect {
/**
* Internal intent used to trigger connection to a wi-fi network.
*/
public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String SSID = "SSID";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String TYPE = "TYPE";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String PASSWORD = "PASSWORD";
private WifiConnect() {
}
}
public static final class Share {
/**
* Give the user a choice of items to encode as a barcode, then render it as a QR Code and
* display onscreen for a friend to scan with their phone.
*/
public static final String ACTION = "com.google.zxing.client.android.SHARE";
private Share() {
}
}
}

View File

@ -1,40 +0,0 @@
package com.zxing.encoding;
import java.util.Hashtable;
import android.graphics.Bitmap;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
/**
* @author Ryan Tang
*
*/
public final class EncodingHandler {
private static final int BLACK = 0xff000000;
public static Bitmap createQRCode(String str,int widthAndHeight) throws WriterException {
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix matrix = new MultiFormatWriter().encode(str,
BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
int width = matrix.getWidth();
int height = matrix.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (matrix.get(x, y)) {
pixels[y * width + x] = BLACK;
}
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (C) 2009 ZXing authors
*
* 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.zxing.view;
import com.google.zxing.ResultPoint;
import com.google.zxing.ResultPointCallback;
public final class ViewfinderResultPointCallback implements ResultPointCallback {
private final ViewfinderView viewfinderView;
public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
this.viewfinderView = viewfinderView;
}
public void foundPossibleResultPoint(ResultPoint point) {
viewfinderView.addPossibleResultPoint(point);
}
}

View File

@ -1,155 +0,0 @@
/*
* Copyright (C) 2008 ZXing authors
*
* 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.zxing.view;
import java.util.Collection;
import java.util.HashSet;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import com.ericssonlabs.R;
import com.google.zxing.ResultPoint;
import com.zxing.camera.CameraManager;
/**
* This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
* transparency outside it, as well as the laser scanner animation and result points.
* 二维码扫描解析框
*/
public final class ViewfinderView extends View {
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
private static final long ANIMATION_DELAY = 100L;
private static final int OPAQUE = 0xFF;
private final Paint paint;
private Bitmap resultBitmap;
private final int maskColor;
private final int resultColor;
private final int frameColor;
private final int laserColor;
private final int resultPointColor;
private int scannerAlpha;
private Collection<ResultPoint> possibleResultPoints;
private Collection<ResultPoint> lastPossibleResultPoints;
// This constructor is used when the class is built from an XML resource.
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
// Initialize these once for performance rather than calling them every time in onDraw().
paint = new Paint();
Resources resources = getResources();
maskColor = resources.getColor(R.color.viewfinder_mask);
resultColor = resources.getColor(R.color.result_view);
frameColor = resources.getColor(R.color.viewfinder_frame);
laserColor = resources.getColor(R.color.viewfinder_laser);
resultPointColor = resources.getColor(R.color.possible_result_points);
scannerAlpha = 0;
possibleResultPoints = new HashSet<ResultPoint>(5);
}
@Override
public void onDraw(Canvas canvas) {
Rect frame = CameraManager.get().getFramingRect();
if (frame == null) {
return;
}
int width = canvas.getWidth();
int height = canvas.getHeight();
// Draw the exterior (i.e. outside the framing rect) darkened
paint.setColor(resultBitmap != null ? resultColor : maskColor);
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
if (resultBitmap != null) {
// Draw the opaque result bitmap over the scanning rectangle
paint.setAlpha(OPAQUE);
canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
} else {
// Draw a two pixel solid black border inside the framing rect
paint.setColor(frameColor);
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
// Draw a red "laser scanner" line through the middle to show decoding is active
paint.setColor(laserColor);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
int middle = frame.height() / 2 + frame.top;
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
Collection<ResultPoint> currentPossible = possibleResultPoints;
Collection<ResultPoint> currentLast = lastPossibleResultPoints;
if (currentPossible.isEmpty()) {
lastPossibleResultPoints = null;
} else {
possibleResultPoints = new HashSet<ResultPoint>(5);
lastPossibleResultPoints = currentPossible;
paint.setAlpha(OPAQUE);
paint.setColor(resultPointColor);
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
}
}
if (currentLast != null) {
paint.setAlpha(OPAQUE / 2);
paint.setColor(resultPointColor);
for (ResultPoint point : currentLast) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
}
}
// Request another update at the animation interval, but only repaint the laser line,
// not the entire viewfinder mask.
postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
}
}
public void drawViewfinder() {
resultBitmap = null;
invalidate();
}
/**
* Draw a bitmap with the result points highlighted instead of the live scanning display.
*
* @param barcode An image of the decoded barcode.
*/
public void drawResultBitmap(Bitmap barcode) {
resultBitmap = barcode;
invalidate();
}
public void addPossibleResultPoint(ResultPoint point) {
possibleResultPoints.add(point);
}
}

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<SurfaceView
android:id="@+id/svCameraScan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<com.zxing.view.ViewfinderView
android:id="@+id/vfvCameraScan"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:background="#000000"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:text="Scan Barcode"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_cancel_scan"
android:layout_width="230dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:layout_marginBottom="75dp"
android:text="Cancel"
android:textSize="15sp"
android:textStyle="bold" />
</RelativeLayout>
</FrameLayout>

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"
android:orientation="vertical" >
<Button
android:id="@+id/btn_scan_barcode"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="Open camera" />
<LinearLayout
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="18sp"
android:text="Scan result" />
<TextView
android:id="@+id/tv_scan_result"
android:layout_width="fill_parent"
android:textSize="18sp"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
</LinearLayout>
<EditText
android:id="@+id/et_qr_string"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:hint="Input the text"/>
<Button
android:id="@+id/btn_add_qrcode"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Generate QRcode" />
<ImageView
android:id="@+id/iv_qr_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_gravity="center"/>
</LinearLayout>

View File

@ -1,2 +0,0 @@
test: test
admin: OBF:1u2a1toa1w8v1tok1u30,admin

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<color name="bg_color">#EDEDED</color>
<color name="contents_text">#ff000000</color>
<color name="encode_view">#ffffffff</color>
<color name="help_button_view">#ffcccccc</color>
<color name="help_view">#ff404040</color>
<color name="possible_result_points">#c0ffff00</color>
<color name="result_image_border">#ffffffff</color>
<color name="result_minor_text">#ffc0c0c0</color>
<color name="result_points">#c000ff00</color>
<color name="result_text">#ffffffff</color>
<color name="result_view">#b0000000</color>
<color name="sbc_header_text">#ff808080</color>
<color name="sbc_header_view">#ffffffff</color>
<color name="sbc_list_item">#fffff0e0</color>
<color name="sbc_layout_view">#ffffffff</color>
<color name="sbc_page_number_text">#ff000000</color>
<color name="sbc_snippet_text">#ff4b4b4b</color>
<color name="share_text">#ff000000</color>
<color name="share_view">#ffffffff</color>
<color name="status_view">#50000000</color>
<color name="status_text">#ffffffff</color>
<color name="transparent">#00000000</color>
<color name="viewfinder_frame">#ff000000</color>
<color name="viewfinder_laser">#ffff0000</color>
<color name="viewfinder_mask">#60000000</color>
<color name="header">#58567D</color>
<color name="grgray">#686868</color>
</resources>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2008 ZXing authors
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.
-->
<resources>
<!-- Messages IDs -->
<item type="id" name="auto_focus"/>
<item type="id" name="decode"/>
<item type="id" name="decode_failed"/>
<item type="id" name="decode_succeeded"/>
<item type="id" name="encode_failed"/>
<item type="id" name="encode_succeeded"/>
<item type="id" name="launch_product_query"/>
<item type="id" name="quit"/>
<item type="id" name="restart_preview"/>
<item type="id" name="return_scan_result"/>
<item type="id" name="search_book_contents_failed"/>
<item type="id" name="search_book_contents_succeeded"/>
</resources>

View File

@ -1,15 +0,0 @@
package com.ericssonlabs;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}

View File

@ -1 +0,0 @@
/build

View File

@ -1,31 +0,0 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion '29.0.0'
defaultConfig {
minSdkVersion 20
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
useLibrary 'org.apache.http.legacy'
productFlavors {
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile files('libs/android-support-v4.jar')
compile files('libs/okhttp-2.1.0.jar')
compile files('libs/okio-1.0.0.jar')
compile files('libs/universal-image-loader-1.9.4.jar')
compile 'com.github.APIJSON:apijson-orm:3.9.0' // compile project(':APIJSONLibrary')
}

View File

@ -1,17 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/Tommy/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -1,13 +0,0 @@
package zuo.biao.library;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View File

@ -1,92 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="zuo.biao.library"
android:versionCode="1"
android:versionName="@string/app_version" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="21" />
<!-- 复制粘贴到你的工程的AndroidManifest.xml内对应位置 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -->
<!-- 需要的权限 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- CommonUtil等类的部分功能需要不需要的功能对应的权限可不复制粘贴 <<<<<< -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- CommonUtil等类的部分功能需要不需要的功能对应的权限可不复制粘贴 >>>>>> -->
<!-- 需要的权限 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<application
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- 更好的适配全面屏 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>-->
<meta-data android:name="android.max_aspect" android:value="2.1" />
<activity
android:name="zuo.biao.library.ui.SelectPictureActivity"
android:screenOrientation="portrait"
android:theme="@style/WindowCompleteAlpha"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="zuo.biao.library.ui.CutPictureActivity"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="zuo.biao.library.ui.WebViewActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustResize|adjustUnspecified" />
<activity
android:name="zuo.biao.library.ui.EditTextInfoActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateVisible|adjustPan|adjustUnspecified" />
<activity
android:name="zuo.biao.library.ui.ServerSettingActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" />
<activity
android:name="zuo.biao.library.ui.TopMenuWindow"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="zuo.biao.library.ui.BottomMenuWindow"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="zuo.biao.library.ui.EditTextInfoWindow"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateVisible|adjustResize|adjustUnspecified" />
<activity
android:name="zuo.biao.library.ui.PlacePickerWindow"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="zuo.biao.library.ui.DatePickerWindow"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="zuo.biao.library.ui.TimePickerWindow"
android:screenOrientation="portrait"
android:theme="@style/Window"
android:windowSoftInputMode="stateAlwaysHidden" />
</application>
<!-- 复制粘贴到你的工程的AndroidManifest.xml内对应位置 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
</manifest>

View File

@ -1,727 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.ActivityPresenter;
import zuo.biao.library.interfaces.OnBottomDragListener;
import zuo.biao.library.manager.SystemBarTintManager;
import zuo.biao.library.manager.ThreadManager;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.ScreenUtil;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**基础android.support.v4.app.FragmentActivity通过继承可获取或使用 里面创建的 组件 方法
* *onFling内控制左右滑动手势操作范围可自定义
* @author Lemon
* @see ActivityPresenter#getActivity
* @see #context
* @see #view
* @see #fragmentManager
* @see #setContentView
* @see #runUiThread
* @see #runThread
* @see #onDestroy
* @use extends BaseActivity, 具体参考 .DemoActivity .DemoFragmentActivity
*/
public abstract class BaseActivity extends FragmentActivity implements ActivityPresenter, OnGestureListener {
private static final String TAG = "BaseActivity";
/**
* 该Activity实例命名为context是因为大部分方法都只需要context写成context使用更方便
* @warn 不能在子类中创建
*/
protected BaseActivity context = null;
/**
* 该Activity的界面即contentView
* @warn 不能在子类中创建
*/
protected View view = null;
/**
* 布局解释器
* @warn 不能在子类中创建
*/
protected LayoutInflater inflater = null;
/**
* Fragment管理器
* @warn 不能在子类中创建
*/
protected FragmentManager fragmentManager = null;
private boolean isAlive = false;
private boolean isRunning = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
context = (BaseActivity) getActivity();
isAlive = true;
fragmentManager = getSupportFragmentManager();
inflater = getLayoutInflater();
threadNameList = new ArrayList<String>();
BaseBroadcastReceiver.register(context, receiver, ACTION_EXIT_APP);
}
/**
* 默认标题旁边的进度环layout.xml中用@id/pbBaseTitle绑定
* @warn 如果子Activity的layout中没有android:id="@id/pbBaseTitle"的pbBaseTitle使用前必须在子Activity中赋值
*/
@Nullable
protected ProgressBar pbBaseTitle;
/**
* 默认标题TextViewlayout.xml中用@id/tvBaseTitle绑定子Activity内调用autoSetTitle方法 会优先使用INTENT_TITLE
* @see #autoSetTitle
* @warn 如果子Activity的layout中没有android:id="@id/tvBaseTitle"的TextView使用前必须在子Activity中赋值
*/
@Nullable
protected TextView tvBaseTitle;
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
// 状态栏沉浸4.4+生效 <<<<<<<<<<<<<<<<<
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
SystemBarTintManager tintManager = new SystemBarTintManager(this);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintResource(R.color.topbar_bg);//状态背景色可传drawable资源
// 状态栏沉浸4.4+生效 >>>>>>>>>>>>>>>>>
pbBaseTitle = (ProgressBar) findViewById(R.id.pbBaseTitle);//绑定默认标题旁ProgressBar
tvBaseTitle = (TextView) findViewById(R.id.tvBaseTitle);//绑定默认标题TextView
}
//底部滑动实现同点击标题栏左右按钮效果<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private OnBottomDragListener onBottomDragListener;
private GestureDetector gestureDetector;
/**设置该Activity界面布局并设置底部左右滑动手势监听
* @param layoutResID
* @param listener
* @use 在子类中
* *1.onCreate中super.onCreate后setContentView(layoutResID, this);
* *2.重写onDragBottom方法并实现滑动事件处理
* *3.在导航栏左右按钮的onClick事件中调用onDragBottom方法
*/
public void setContentView(int layoutResID, OnBottomDragListener listener) {
setContentView(layoutResID);
onBottomDragListener = listener;
gestureDetector = new GestureDetector(this, this);//初始化手势监听类
view = inflater.inflate(layoutResID, null);
view.setOnTouchListener(new OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
}
//底部滑动实现同点击标题栏左右按钮效果>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**
* 用于 打开activity以及activity之间的通讯传值一些通讯相关基本操作打电话发短信等
*/
protected Intent intent = null;
/**
* 退出时之前的界面进入动画,可在finish();前通过改变它的值来改变动画效果
*/
protected int enterAnim = R.anim.fade;
/**
* 退出时该界面动画,可在finish();前通过改变它的值来改变动画效果
*/
protected int exitAnim = R.anim.right_push_out;
// /**通过id查找并获取控件使用时不需要强转
// * @param id
// * @return
// */
// @SuppressWarnings("unchecked")
// public <V extends View> V findViewById(int id) {
// return (V) view.findViewById(id);
// }
/**通过id查找并获取控件并setOnClickListener
* @param id
* @param l
* @return
*/
@SuppressWarnings("unchecked")
public <V extends View> V findViewById(int id, OnClickListener l) {
V v = (V) findViewById(id);
v.setOnClickListener(l);
return v;
}
//自动设置标题方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**自动把标题设置为上个Activity传入的INTENT_TITLE建议在子类initView中使用
* *这个方法没有returntvTitle = tvBaseTitle直接用tvBaseTitle
* @must 在UI线程中调用
*/
protected void autoSetTitle() {
tvBaseTitle = autoSetTitle(tvBaseTitle);
}
/**自动把标题设置为上个Activity传入的INTENT_TITLE建议在子类initView中使用
* @param tvTitle
* @return tvTitle 返回tvTitle是为了可以写成一行 tvTitle = autoSetTitle((TextView) findViewById(titleResId));
* @must 在UI线程中调用
*/
protected TextView autoSetTitle(TextView tvTitle) {
if (tvTitle != null) {
String title = getIntent().getStringExtra(INTENT_TITLE);
if (StringUtil.isNotEmpty(title, false)) {
tvTitle.setText(StringUtil.getString(title));
}
if (pbBaseTitle != null) {
tvTitle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isShowingProgress() == false) {
initData();
}
}
});
}
}
return tvTitle;
}
//自动设置标题方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//显示与关闭进度弹窗方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**正在显示进度
* @return
*/
public boolean isShowingProgress() {
if (pbBaseTitle != null) {
return pbBaseTitle.getVisibility() == View.VISIBLE;
}
if (progressDialog != null) {
return progressDialog.isShowing();
}
return false;
}
/**
* 进度弹窗
*/
protected ProgressDialog progressDialog = null;
/**展示加载进度条,无标题
* stringResId = R.string.loading
*/
public void showProgressDialog() {
showProgressDialog(R.string.loading);
}
/**展示加载进度条,无标题
* @param stringResId
*/
public void showProgressDialog(int stringResId) {
try {
showProgressDialog(null, context.getResources().getString(stringResId));
} catch (Exception e) {
Log.e(TAG, "showProgressDialog showProgressDialog(null, context.getResources().getString(stringResId));");
}
}
/**展示加载进度条,无标题
* @param message
*/
public void showProgressDialog(String message) {
showProgressDialog(null, message);
}
/**展示加载进度条
* @param title 标题
* @param message 信息
*/
public void showProgressDialog(final String title, final String message) {
runUiThread(new Runnable() {
@Override
public void run() {
if (pbBaseTitle != null) {
pbBaseTitle.setVisibility(View.VISIBLE);
String s = tvBaseTitle == null ? null : StringUtil.isNotEmpty(message, false) ? message : title;
if (StringUtil.isNotEmpty(s, true)) {
tvBaseTitle.setText(s);
}
return;
}
if (progressDialog == null) {
progressDialog = new ProgressDialog(context);
}
if(progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (StringUtil.isNotEmpty(title, false)) {
progressDialog.setTitle(title);
}
if (StringUtil.isNotEmpty(message, false)) {
progressDialog.setMessage(message);
}
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
});
}
/**隐藏加载进度
*/
public void dismissProgressDialog() {
runUiThread(new Runnable() {
@Override
public void run() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (pbBaseTitle != null) {
pbBaseTitle.setVisibility(View.GONE);
}
}
});
}
//显示与关闭进度弹窗方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//启动新Activity方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**打开新的Activity向左滑入效果
* @param intent
*/
public void toActivity(Intent intent) {
toActivity(intent, true);
}
/**打开新的Activity
* @param intent
* @param showAnimation
*/
public void toActivity(Intent intent, boolean showAnimation) {
toActivity(intent, -1, showAnimation);
}
/**打开新的Activity向左滑入效果
* @param intent
* @param requestCode
*/
public void toActivity(Intent intent, int requestCode) {
toActivity(intent, requestCode, true);
}
/**打开新的Activity
* @param intent
* @param requestCode
* @param showAnimation
*/
public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) {
runUiThread(new Runnable() {
@Override
public void run() {
if (intent == null) {
Log.w(TAG, "toActivity intent == null >> return;");
return;
}
//fragment中使用context.startActivity会导致在fragment中不能正常接收onActivityResult
if (requestCode < 0) {
startActivity(intent);
} else {
startActivityForResult(intent, requestCode);
}
if (showAnimation) {
overridePendingTransition(R.anim.right_push_in, R.anim.hold);
} else {
overridePendingTransition(R.anim.null_anim, R.anim.null_anim);
}
}
});
}
//启动新Activity方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//show short toast 方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param stringResId
*/
public void showShortToast(int stringResId) {
try {
showShortToast(context.getResources().getString(stringResId));
} catch (Exception e) {
Log.e(TAG, "showShortToast context.getResources().getString(resId)" +
" >> catch (Exception e) {" + e.getMessage());
}
}
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param string
*/
public void showShortToast(String string) {
showShortToast(string, false);
}
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param string
* @param isForceDismissProgressDialog
*/
public void showShortToast(final String string, final boolean isForceDismissProgressDialog) {
runUiThread(new Runnable() {
@Override
public void run() {
if (isForceDismissProgressDialog) {
dismissProgressDialog();
}
Toast.makeText(context, "" + string, Toast.LENGTH_SHORT).show();
}
});
}
//show short toast 方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//运行线程 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**在UI线程中运行建议用这个方法代替runOnUiThread
* @param action
*/
public final void runUiThread(Runnable action) {
if (isAlive() == false) {
Log.w(TAG, "runUiThread isAlive() == false >> return;");
return;
}
runOnUiThread(action);
}
/**
* 线程名列表
*/
protected List<String> threadNameList;
/**运行线程
* @param name
* @param runnable
* @return
*/
public final Handler runThread(String name, Runnable runnable) {
if (isAlive() == false) {
Log.w(TAG, "runThread isAlive() == false >> return null;");
return null;
}
name = StringUtil.getTrimedString(name);
Handler handler = ThreadManager.getInstance().runThread(name, runnable);
if (handler == null) {
Log.e(TAG, "runThread handler == null >> return null;");
return null;
}
if (threadNameList.contains(name) == false) {
threadNameList.add(name);
}
return handler;
}
//运行线程 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Activity的返回按钮和底部弹窗的取消按钮几乎是必备正好原生支持反射而其它比如Fragment极少用到也不支持反射<<<<<<<<<
/**返回按钮被点击默认处理是onBottomDragListener.onDragBottom(false)重写可自定义事件处理
* @param v
* @use layout.xml中的组件添加android:onClick="onReturnClick"即可
* @warn 只能在Activity对应的contentView layout中使用
* *给对应View setOnClickListener会导致android:onClick="onReturnClick"失效
*/
@Override
public void onReturnClick(View v) {
Log.d(TAG, "onReturnClick >>>");
if (onBottomDragListener != null) {
onBottomDragListener.onDragBottom(false);
} else {
onBackPressed();//会从最外层子类调finish();BaseBottomWindow就是示例
}
}
/**前进按钮被点击默认处理是onBottomDragListener.onDragBottom(true)重写可自定义事件处理
* @param v
* @use layout.xml中的组件添加android:onClick="onForwardClick"即可
* @warn 只能在Activity对应的contentView layout中使用
* *给对应View setOnClickListener会导致android:onClick="onForwardClick"失效
*/
@Override
public void onForwardClick(View v) {
Log.d(TAG, "onForwardClick >>>");
if (onBottomDragListener != null) {
onBottomDragListener.onDragBottom(true);
}
}
//Activity常用导航栏右边按钮而且底部弹窗BottomWindow的确定按钮是必备而其它比如Fragment极少用到也不支持反射>>>>>
@Override
public final boolean isAlive() {
return isAlive && context != null;// & ! isFinishing();导致finishonDestroy内runUiThread不可用
}
@Override
public final boolean isRunning() {
return isRunning & isAlive();
}
/**一般用于对不支持的数据的处理比如onCreate中获取到不能接受的id(id<=0)可以这样处理
*/
public void finishWithError(String error) {
showShortToast(error);
enterAnim = exitAnim = R.anim.null_anim;
finish();
}
@Override
public void finish() {
super.finish();//必须写在最前才能显示自定义动画
runUiThread(new Runnable() {
@Override
public void run() {
if (enterAnim > 0 && exitAnim > 0) {
try {
overridePendingTransition(enterAnim, exitAnim);
} catch (Exception e) {
Log.e(TAG, "finish overridePendingTransition(enterAnim, exitAnim);" +
" >> catch (Exception e) { " + e.getMessage());
}
}
}
});
}
@Override
protected void onResume() {
Log.d(TAG, "\n onResume <<<<<<<<<<<<<<<<<<<<<<<");
super.onResume();
isRunning = true;
Log.d(TAG, "onResume >>>>>>>>>>>>>>>>>>>>>>>>\n");
}
@Override
protected void onPause() {
Log.d(TAG, "\n onPause <<<<<<<<<<<<<<<<<<<<<<<");
super.onPause();
isRunning = false;
Log.d(TAG, "onPause >>>>>>>>>>>>>>>>>>>>>>>>\n");
}
/**销毁并回收内存
* @warn 子类如果要使用这个方法内用到的变量应重写onDestroy方法并在super.onDestroy();前操作
*/
@Override
protected void onDestroy() {
Log.d(TAG, "\n onDestroy <<<<<<<<<<<<<<<<<<<<<<<");
dismissProgressDialog();
BaseBroadcastReceiver.unregister(context, receiver);
ThreadManager.getInstance().destroyThread(threadNameList);
if (view != null) {
try {
view.destroyDrawingCache();
} catch (Exception e) {
Log.w(TAG, "onDestroy try { view.destroyDrawingCache();" +
" >> } catch (Exception e) {\n" + e.getMessage());
}
}
isAlive = false;
isRunning = false;
super.onDestroy();
inflater = null;
view = null;
pbBaseTitle = null;
tvBaseTitle = null;
fragmentManager = null;
progressDialog = null;
threadNameList = null;
intent = null;
context = null;
Log.d(TAG, "onDestroy >>>>>>>>>>>>>>>>>>>>>>>>\n");
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent == null ? null : intent.getAction();
if (isAlive() == false || StringUtil.isNotEmpty(action, true) == false) {
Log.e(TAG, "receiver.onReceive isAlive() == false" +
" || StringUtil.isNotEmpty(action, true) == false >> return;");
return;
}
if (ACTION_EXIT_APP.equals(action)) {
finish();
}
}
};
//手机返回键和菜单键实现同点击标题栏左右按钮效果<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private boolean isOnKeyLongPress = false;
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
isOnKeyLongPress = true;
return true;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (isOnKeyLongPress) {
isOnKeyLongPress = false;
return true;
}
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (onBottomDragListener != null) {
onBottomDragListener.onDragBottom(false);
return true;
}
break;
case KeyEvent.KEYCODE_MENU:
if (onBottomDragListener != null) {
onBottomDragListener.onDragBottom(true);
return true;
}
break;
default:
break;
}
return super.onKeyUp(keyCode, event);
}
//手机返回键和菜单键实现同点击标题栏左右按钮效果>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//底部滑动实现同点击标题栏左右按钮效果<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// /*原来实现全局滑动返回的代码OnFinishListener已删除可以自己写一个或者
// * 用onBottomDragListener.onDragBottom(false);代替onFinishListener.finish();**/
// if (onFinishListener != null) {
//
// float maxDragHeight = getResources().getDimension(R.dimen.page_drag_max_height);
// float distanceY = e2.getRawY() - e1.getRawY();
// if (distanceY < maxDragHeight && distanceY > - maxDragHeight) {
//
// float minDragWidth = getResources().getDimension(R.dimen.page_drag_min_width);
// float distanceX = e2.getRawX() - e1.getRawX();
// if (distanceX > minDragWidth) {
// onFinishListener.finish();
// return true;
// }
// }
// }
//底部滑动实现同点击标题栏左右按钮效果
if (onBottomDragListener != null && e1.getRawY() > ScreenUtil.getScreenSize(this)[1]
- ((int) getResources().getDimension(R.dimen.bottom_drag_height))) {
float maxDragHeight = getResources().getDimension(R.dimen.bottom_drag_max_height);
float distanceY = e2.getRawY() - e1.getRawY();
if (distanceY < maxDragHeight && distanceY > - maxDragHeight) {
float minDragWidth = getResources().getDimension(R.dimen.bottom_drag_min_width);
float distanceX = e2.getRawX() - e1.getRawX();
if (distanceX > minDragWidth) {
onBottomDragListener.onDragBottom(false);
return true;
} else if (distanceX < - minDragWidth) {
onBottomDragListener.onDragBottom(true);
return true;
}
}
}
return false;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (gestureDetector != null) {
gestureDetector.onTouchEvent(ev);
}
return super.dispatchTouchEvent(ev);
}
//底部滑动实现同点击标题栏左右按钮效果>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,184 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.interfaces.OnReachViewBorderListener;
import zuo.biao.library.util.CommonUtil;
import zuo.biao.library.util.SettingUtil;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**基础Adapter
* <br> 适用于ListView,GridView等AbsListView的子类
* @author Lemon
* @warn 出于性能考虑里面很多方法对变量(比如list)都没有判断应在adapter外判断
* @param <T> 数据模型(model/JavaBean)
* @use extends BaseAdapter<T>, 具体参考.DemoAdapter
* <br> 预加载使用
* <br> 1.在子类getView中最后 return super.getView(position, convertView, parent);//非必须只在预加载用到
* <br> 2.在使用子类的类中调用子类setOnReachViewBorderListener方法这个方法就在这个类//非必须
*/
public abstract class BaseAdapter<T> extends android.widget.BaseAdapter {
// private static final String TAG = "BaseAdapter";
/**
* 管理整个界面的Activity实例
*/
public Activity context;
/**
* 布局解释器,用来实例化列表的item的界面
*/
public LayoutInflater inflater;
/**
* 资源获取器用于获取res目录下的文件及文件中的内容等
*/
public Resources resources;
public BaseAdapter(Activity context) {
this.context = context;
inflater = context.getLayoutInflater();
resources = context.getResources();
}
/**
* 传进来的数据列表
*/
public List<T> list;
public List<T> getList() {
return list;
}
/**刷新列表
*/
public synchronized void refresh(List<T> list) {
this.list = list == null ? null : new ArrayList<T>(list);
notifyDataSetChanged();
}
@Override
public int getCount() {
return list == null ? 0 : list.size();
}
/**获取item数据
*/
@Override
public T getItem(int position) {
return list.get(position);
}
/**获取item的id如果不能满足需求可在子类重写
* @param position
* @return position
*/
@Override
public long getItemId(int position) {
return position;
}
//预加载可不使用 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected OnReachViewBorderListener onReachViewBorderListener;
/**设置到达parent的边界的监听
* @param onReachViewBorderListener
*/
public void setOnReachViewBorderListener(OnReachViewBorderListener onReachViewBorderListener) {
this.onReachViewBorderListener = onReachViewBorderListener;
}
/**
* 预加载提前数
* <br > = 0 - 列表滚到底部(最后一个Item View显示)时加载更多
* <br > < 0 - 禁用加载更多
* <br > > 0 - 列表滚到倒数第preloadCount个Item View显示时加载更多
* @use 可在子类getView被调用前(可以是在构造器内)赋值
*/
protected int preloadCount = 0;
/**获取item对应View的方法带item滑到底部等监听
* @param position
* @param convertView
* @param parent
* @return
* @use 子类的getView中最后 return super.getView(position, convertView, parent);
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (SettingUtil.preload && onReachViewBorderListener != null && position >= getCount() - 1 - preloadCount) {
onReachViewBorderListener.onReach(OnReachViewBorderListener.TYPE_BOTTOM, parent);
}
return convertView;
}
//预加载可不使用 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//show short toast 方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param stringResId
*/
public void showShortToast(int stringResId) {
CommonUtil.showShortToast(context, stringResId);
}
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param string
*/
public void showShortToast(String string) {
CommonUtil.showShortToast(context, string);
}
//show short toast 方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//启动新Activity方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**打开新的Activity向左滑入效果
* @param intent
*/
public void toActivity(final Intent intent) {
CommonUtil.toActivity(context, intent);
}
/**打开新的Activity
* @param intent
* @param showAnimation
*/
public void toActivity(final Intent intent, final boolean showAnimation) {
CommonUtil.toActivity(context, intent, showAnimation);
}
/**打开新的Activity向左滑入效果
* @param intent
* @param requestCode
*/
public void toActivity(final Intent intent, final int requestCode) {
CommonUtil.toActivity(context, intent, requestCode);
}
/**打开新的Activity
* @param intent
* @param requestCode
* @param showAnimation
*/
public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) {
CommonUtil.toActivity(context, intent, requestCode, showAnimation);
}
//启动新Activity方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,64 +0,0 @@
package zuo.biao.library.base;
import zuo.biao.library.R;
import zuo.biao.library.util.DataKeeper;
import zuo.biao.library.util.ImageLoaderUtil;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.SettingUtil;
import android.app.Application;
/**基础Application
* @author Lemon
* @see #init
* @use extends BaseApplication 在你的Application的onCreate方法中BaseApplication.init(this);
*/
public class BaseApplication extends Application {
private static final String TAG = "BaseApplication";
public BaseApplication() {
}
private static Application instance;
public static Application getInstance() {
return instance;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "项目启动 >>>>>>>>>>>>>>>>>>>> \n\n");
init(this);
}
/**初始化方法
* @param application
* @must 调用init方法且只能调用一次如果extends BaseApplication会自动调用
*/
public static void init(Application application) {
instance = application;
if (instance == null) {
Log.e(TAG, "\n\n\n\n\n !!!!!! 调用BaseApplication中的init方法instance不能为null !!!" +
"\n <<<<<< init instance == null >>>>>>>> \n\n\n\n");
}
DataKeeper.init(instance);
SettingUtil.init(instance);
ImageLoaderUtil.init(instance);
}
/**获取应用名
* @return
*/
public String getAppName() {
return getResources().getString(R.string.app_name);
}
/**获取应用版本名(显示给用户看的)
* @return
*/
public String getAppVersion() {
return getResources().getString(R.string.app_version);
}
}

View File

@ -1,276 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import zuo.biao.library.util.Log;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.view.View.OnClickListener;
/**基础底部标签Activity
* @author Lemon
* @use extends BaseBottomTabActivity
*/
public abstract class BaseBottomTabActivity extends BaseActivity {
private static final String TAG = "BaseBottomTabActivity";
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected static int[] tabClickIds;
protected View[] vTabClickViews;
protected View[][] vTabSelectViews;
@Override
public void initView() {// 必须调用
tabClickIds = getTabClickIds();
vTabClickViews = new View[getCount()];
for (int i = 0; i < getCount(); i++) {
vTabClickViews[i] = findViewById(tabClickIds[i]);
}
int[][] tabSelectIds = getTabSelectIds();
if (tabSelectIds != null && tabSelectIds.length > 0) {
vTabSelectViews = new View[tabSelectIds.length][getCount()];
for (int i = 0; i < tabSelectIds.length; i++) {
if (tabSelectIds[i] != null) {
for (int j = 0; j < tabSelectIds[i].length; j++) {
vTabSelectViews[i][j] = findViewById(tabSelectIds[i][j]);
}
}
}
}
}
/**选择tab在selectFragment里被调用
* @param position
*/
protected abstract void selectTab(int position);
/**设置选中状态
* @param position
*/
protected void setTabSelection(int position) {
if (vTabSelectViews == null) {
Log.e(TAG, "setTabSelection vTabSelectViews == null >> return;");
return;
}
for (int i = 0; i < vTabSelectViews.length; i++) {
if (vTabSelectViews[i] == null) {
Log.w(TAG, "setTabSelection vTabSelectViews[" + i + "] == null >> continue;");
continue;
}
for (int j = 0; j < vTabSelectViews[i].length; j++) {
vTabSelectViews[i][j].setSelected(j == position);
}
}
}
protected int currentPosition = 0;
/**选择并显示fragment
* @param position
*/
public void selectFragment(int position) {
if (fragments == null || fragments.length != getCount()) {
removeAll();
fragments = new Fragment[getCount()];
}
if (currentPosition == position) {
if (fragments[position] != null && fragments[position].isVisible()) {
Log.e(TAG, "selectFragment currentPosition == position" +
" >> fragments[position] != null && fragments[position].isVisible()" +
" >> return; ");
return;
}
}
if (fragments[position] == null) {
fragments[position] = getFragment(position);
}
// 用全局的fragmentTransaction因为already committed 崩溃
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.hide(fragments[currentPosition]);
if (fragments[position].isAdded() == false) {
fragmentTransaction.add(getFragmentContainerResId(), fragments[position]);
}
fragmentTransaction.show(fragments[position]).commit();
//消耗资源很少不像Fragment<<<<<<
setTabSelection(position);
selectTab(position);
//消耗资源很少不像Fragment>>>>>>
this.currentPosition = position;
};
protected void reload(int position) {
remove(position);
if (position == currentPosition) {
selectFragment(position);
}
}
protected void reloadAll() {
runUiThread(new Runnable() {
@Override
public void run() {
removeAll(true);
selectFragment(currentPosition);
}
});
}
protected void remove(int position) {
remove(position, false);
}
protected void remove(int position, boolean destroy) {
if (fragments != null && position >= 0 && position < fragments.length && fragments[position] != null) {
try {
fragmentManager.beginTransaction().remove(fragments[position]).commit();
} catch (Exception e) {
Log.e(TAG, "remove try { fragmentManager.beginTransaction().remove(fragments[position]).commit();" +
" } catch (Exception e) {\n" + e.getMessage());
destroy = true;
}
if (destroy) {
fragments[position].onDestroy();
fragments[position] = null;
}
}
}
protected void removeAll() {
removeAll(false);
}
protected void removeAll(boolean destroy) {
if (fragments != null) {
for (int i = 0; i < fragments.length; i++) {
remove(i, destroy);
}
}
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected Fragment[] fragments;
@Override
public void initData() {// 必须调用
// fragmentActivity子界面初始化<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
selectFragment(currentPosition);
// fragmentActivity子界面初始化>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
/**获取tab内设置点击事件的View的id
* @param position
* @return
*/
protected abstract int[] getTabClickIds();
/**获取tab内设置选择事件的View的idsetSelected(position == currentPositon)
* @return
* @warn 返回int[leghth0][leghth1]必须满足leghth0 >= 1 && leghth1 = getCount() = getTabClickIds().length
*/
protected abstract int[][] getTabSelectIds();
/**获取Fragment容器的id
* @return
*/
public abstract int getFragmentContainerResId();
/**获取新的Fragment
* @param position
* @return
*/
protected abstract Fragment getFragment(int position);
/**获取Tab(或Fragment)的数量
* @return
*/
public int getCount() {
return tabClickIds == null ? 0 :tabClickIds.length;
}
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
for (int i = 0; i < vTabClickViews.length; i++) {
final int which = i;
vTabClickViews[which].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
selectFragment(which);
}
});
}
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,166 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import zuo.biao.library.R;
import zuo.biao.library.util.Log;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.animation.AnimationUtils;
/**基础底部弹出界面Activity
* @author Lemon
* @warn 不要在子类重复这个类中onCreate中的代码
* @use extends BaseBottomWindow, 具体参考.DemoBottomWindow
*/
public abstract class BaseBottomWindow extends BaseActivity {
private static final String TAG = "BaseBottomWindow";
public static final String INTENT_ITEMS = "INTENT_ITEMS";
public static final String INTENT_ITEM_IDS = "INTENT_ITEM_IDS";
public static final String RESULT_TITLE = "RESULT_TITLE";
public static final String RESULT_ITEM = "RESULT_ITEM";
public static final String RESULT_ITEM_ID = "RESULT_ITEM_ID";
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected View vBaseBottomWindowRoot;//子Activity全局背景View
/**
* 如果在子类中调用(即super.initView());则view必须含有initView中初始化用到的id(@Nullable标记)且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
*/
@Override
public void initView() {// 必须调用
enterAnim = exitAnim = R.anim.null_anim;
vBaseBottomWindowRoot = findViewById(R.id.vBaseBottomWindowRoot);
vBaseBottomWindowRoot.startAnimation(AnimationUtils.loadAnimation(context, R.anim.bottom_window_enter));
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initData() {// 必须调用
}
/**
* 设置需要返回的结果
*/
protected abstract void setResult();
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
// vBaseBottomWindowRoot.setOnClickListener(new OnClickListener() {
//
// @Override
// public void onClick(View v) {
// finish();
// }
// });
}
@Override
public void onForwardClick(View v) {
setResult();
finish();
}
@SuppressLint("HandlerLeak")
public Handler exitHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
BaseBottomWindow.super.finish();
}
};
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private boolean isExit = false;
/**带动画退出,并使退出事件只响应一次
*/
@Override
public void finish() {
Log.d(TAG, "finish >>> isExit = " + isExit);
if (isExit) {
return;
}
isExit = true;
vBaseBottomWindowRoot.startAnimation(AnimationUtils.loadAnimation(context, R.anim.bottom_window_exit));
vBaseBottomWindowRoot.setVisibility(View.GONE);
exitHandler.sendEmptyMessageDelayed(0, 200);
}
@Override
protected void onDestroy() {
super.onDestroy();
vBaseBottomWindowRoot = null;
}
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,152 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.Arrays;
import java.util.List;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.StringUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.annotation.Nullable;
/**基础广播接收器
* @author Lemon
* @use 自定义BroadcastReceiver - extends BaseBroadcastReceiver其它 - 直接使用里面的静态方法
* @must 调用register和unregister方法
*/
public abstract class BaseBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "BaseBroadcastReceiver";
/**接收信息监听回调
*/
public interface OnReceiveListener{
void onReceive(Context context, Intent intent);
}
protected OnReceiveListener onReceiveListener = null;
/**注册接收信息监听
* @must 在register后unregister前调用
* @param onReceiveListener
*/
public void setOnReceiveListener(OnReceiveListener onReceiveListener) {
this.onReceiveListener = onReceiveListener;
}
protected Context context = null;
public BaseBroadcastReceiver(Context context) {
this.context = context;
}
/**接收信息监听回调方法
*/
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive intent = " + intent);
if (onReceiveListener != null) {
onReceiveListener.onReceive(context, intent);
}
}
/**
* 注册广播接收器
* @use 一般在Activity或Fragment的onCreate中调用
*/
public abstract BaseBroadcastReceiver register();
/**
* 取消注册广播接收器
* @use 一般在Activity或Fragment的onDestroy中调用
*/
public abstract void unregister();
/**注册广播接收器
* @param context
* @param receiver
* @param action
* @return
*/
public static BroadcastReceiver register(Context context, @Nullable BroadcastReceiver receiver, String action) {
return register(context, receiver, new String[] {action});
}
/**注册广播接收器
* @param context
* @param receiver
* @param actions
* @return
*/
public static BroadcastReceiver register(Context context, @Nullable BroadcastReceiver receiver, String[] actions) {
return register(context, receiver, actions == null ? null : Arrays.asList(actions));
}
/**注册广播接收器
* @param context
* @param receiver
* @param actionList
* @return
*/
public static BroadcastReceiver register(Context context, @Nullable BroadcastReceiver receiver, List<String> actionList) {
IntentFilter filter = new IntentFilter();
for (String action : actionList) {
if (StringUtil.isNotEmpty(action, true)) {
filter.addAction(StringUtil.getTrimedString(action));
}
}
return register(context, receiver, filter);
}
/**注册广播接收器
* @param context
* @param receiver
* @param filter
* @return
*/
public static BroadcastReceiver register(Context context, @Nullable BroadcastReceiver receiver, IntentFilter filter) {
Log.i(TAG, "register >>>");
if (context == null || filter == null) {
Log.e(TAG, "register context == null || filter == null >> return;");
return receiver;
}
context.registerReceiver(receiver, filter);
return receiver;
}
/**取消注册广播接收器
* @param context
* @param receiver
* @return
*/
public static void unregister(Context context, BroadcastReceiver receiver) {
Log.i(TAG, "unregister >>>");
if (context == null || receiver == null) {
Log.e(TAG, "unregister context == null || receiver == null >> return;");
return;
}
try {
context.unregisterReceiver(receiver);
} catch (Exception e) {
Log.e(TAG, "unregister try { context.unregisterReceiver(receiver);" +
" } catch (Exception e) { \n" + e.getMessage());
}
}
}

View File

@ -1,377 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.FragmentPresenter;
import zuo.biao.library.util.Log;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
/**基础android.support.v4.app.Fragment通过继承可获取或使用 里面创建的 组件 方法
* @author Lemon
* @see #context
* @see #view
* @see #onCreateView
* @see #setContentView
* @see #runUiThread
* @see #runThread
* @see #onDestroy
* @use extends BaseFragment, 具体参考.DemoFragment
*/
public abstract class BaseFragment extends Fragment implements FragmentPresenter {
private static final String TAG = "BaseFragment";
/**
* 添加该Fragment的Activity
* @warn 不能在子类中创建
*/
protected BaseActivity context = null;
/**
* 该Fragment全局视图
* @must 非abstract子类的onCreateView中return view;
* @warn 不能在子类中创建
*/
protected View view = null;
/**
* 布局解释器
* @warn 不能在子类中创建
*/
protected LayoutInflater inflater = null;
/**
* 添加这个Fragment视图的布局
* @warn 不能在子类中创建
*/
@Nullable
protected ViewGroup container = null;
private boolean isAlive = false;
private boolean isRunning = false;
/**
* @must 在非abstract子类的onCreateView中super.onCreateView且return view;
*/
@Override
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){
context = (BaseActivity) getActivity();
isAlive = true;
this.inflater = inflater;
this.container = container;
return view;
}
/**设置界面布局
* @warn 最多调用一次
* @param layoutResID
* @use 在onCreateView后调用
*/
public void setContentView(int layoutResID) {
setContentView(inflater.inflate(layoutResID, container, false));
}
/**设置界面布局
* @warn 最多调用一次
* @param view
* @use 在onCreateView后调用
*/
public void setContentView(View v) {
setContentView(v, null);
}
/**设置界面布局
* @warn 最多调用一次
* @param view
* @param params
* @use 在onCreateView后调用
*/
public void setContentView(View v, ViewGroup.LayoutParams params) {
view = v;
}
/**
* 该Fragment在Activity添加的所有Fragment中的位置通过ARGUMENT_POSITION设置
* @must 只使用getPosition方法来获取position保证position正确
*/
private int position = -1;
/**获取该Fragment在Activity添加的所有Fragment中的位置
*/
public int getPosition() {
if (position < 0) {
argument = getArguments();
if (argument != null) {
position = argument.getInt(ARGUMENT_POSITION, position);
}
}
return position;
}
/**
* 可用于 打开activity与fragmentfragment与fragment之间的通讯传值
*/
protected Bundle argument = null;
/**
* 可用于 打开activity以及activity之间的通讯传值一些通讯相关基本操作打电话发短信等
*/
protected Intent intent = null;
/**通过id查找并获取控件使用时不需要强转
* @warn 调用前必须调用setContentView
* @param id
* @return
*/
@SuppressWarnings("unchecked")
public <V extends View> V findViewById(int id) {
return (V) view.findViewById(id);
}
/**通过id查找并获取控件并setOnClickListener
* @param id
* @param l
* @return
*/
public <V extends View> V findViewById(int id, OnClickListener l) {
V v = findViewById(id);
v.setOnClickListener(l);
return v;
}
public Intent getIntent() {
return context.getIntent();
}
//运行线程<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**在UI线程中运行建议用这个方法代替runOnUiThread
* @param action
*/
public final void runUiThread(Runnable action) {
if (isAlive() == false) {
Log.w(TAG, "runUiThread isAlive() == false >> return;");
return;
}
context.runUiThread(action);
}
/**运行线程
* @param name
* @param runnable
* @return
*/
public final Handler runThread(String name, Runnable runnable) {
if (isAlive() == false) {
Log.w(TAG, "runThread isAlive() == false >> return null;");
return null;
}
return context.runThread(name + getPosition(), runnable);//name, runnable);同一Activity出现多个同名Fragment可能会出错
}
//运行线程>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//进度弹窗<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**展示加载进度条,无标题
* @param stringResId
*/
public void showProgressDialog(int stringResId){
if (isAlive() == false) {
Log.w(TAG, "showProgressDialog isAlive() == false >> return;");
return;
}
context.showProgressDialog(context.getResources().getString(stringResId));
}
/**展示加载进度条,无标题
* @param dialogMessage
*/
public void showProgressDialog(String dialogMessage){
if (isAlive() == false) {
Log.w(TAG, "showProgressDialog isAlive() == false >> return;");
return;
}
context.showProgressDialog(dialogMessage);
}
/**展示加载进度条
* @param dialogTitle 标题
* @param dialogMessage 信息
*/
public void showProgressDialog(String dialogTitle, String dialogMessage){
if (isAlive() == false) {
Log.w(TAG, "showProgressDialog isAlive() == false >> return;");
return;
}
context.showProgressDialog(dialogTitle, dialogMessage);
}
/** 隐藏加载进度
*/
public void dismissProgressDialog(){
if (isAlive() == false) {
Log.w(TAG, "dismissProgressDialog isAlive() == false >> return;");
return;
}
context.dismissProgressDialog();
}
//进度弹窗>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//启动Activity<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**打开新的Activity向左滑入效果
* @param intent
*/
public void toActivity(Intent intent) {
toActivity(intent, true);
}
/**打开新的Activity
* @param intent
* @param showAnimation
*/
public void toActivity(Intent intent, boolean showAnimation) {
toActivity(intent, -1, showAnimation);
}
/**打开新的Activity向左滑入效果
* @param intent
* @param requestCode
*/
public void toActivity(Intent intent, int requestCode) {
toActivity(intent, requestCode, true);
}
/**打开新的Activity
* @param intent
* @param requestCode
* @param showAnimation
*/
public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) {
runUiThread(new Runnable() {
@Override
public void run() {
if (intent == null) {
Log.w(TAG, "toActivity intent == null >> return;");
return;
}
//fragment中使用context.startActivity会导致在fragment中不能正常接收onActivityResult
if (requestCode < 0) {
startActivity(intent);
} else {
startActivityForResult(intent, requestCode);
}
if (showAnimation) {
context.overridePendingTransition(R.anim.right_push_in, R.anim.hold);
} else {
context.overridePendingTransition(R.anim.null_anim, R.anim.null_anim);
}
}
});
}
//启动Activity>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//show short toast<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param stringResId
*/
public void showShortToast(int stringResId) {
if (isAlive() == false) {
Log.w(TAG, "showProgressDialog isAlive() == false >> return;");
return;
}
context.showShortToast(stringResId);
}
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param string
*/
public void showShortToast(String string) {
if (isAlive() == false) {
Log.w(TAG, "showProgressDialog isAlive() == false >> return;");
return;
}
context.showShortToast(string);
}
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param string
* @param isForceDismissProgressDialog
*/
public void showShortToast(String string, boolean isForceDismissProgressDialog) {
if (isAlive() == false) {
Log.w(TAG, "showProgressDialog isAlive() == false >> return;");
return;
}
context.showShortToast(string, isForceDismissProgressDialog);
}
//show short toast>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
public final boolean isAlive() {
return isAlive && context != null;// & ! isRemoving();导致finishonDestroy内runUiThread不可用
}
@Override
public final boolean isRunning() {
return isRunning & isAlive();
}
@Override
public void onResume() {
Log.d(TAG, "\n onResume <<<<<<<<<<<<<<<<<<<<<<<");
super.onResume();
isRunning = true;
Log.d(TAG, "onResume >>>>>>>>>>>>>>>>>>>>>>>>\n");
}
@Override
public void onPause() {
Log.d(TAG, "\n onPause <<<<<<<<<<<<<<<<<<<<<<<");
super.onPause();
isRunning = false;
Log.d(TAG, "onPause >>>>>>>>>>>>>>>>>>>>>>>>\n");
}
/**销毁并回收内存
* @warn 子类如果要使用这个方法内用到的变量应重写onDestroy方法并在super.onDestroy();前操作
*/
@Override
public void onDestroy() {
Log.d(TAG, "\n onDestroy <<<<<<<<<<<<<<<<<<<<<<<");
dismissProgressDialog();
if (view != null) {
try {
view.destroyDrawingCache();
} catch (Exception e) {
Log.w(TAG, "onDestroy try { view.destroyDrawingCache();" +
" >> } catch (Exception e) {\n" + e.getMessage());
}
}
isAlive = false;
isRunning = false;
super.onDestroy();
view = null;
inflater = null;
container = null;
intent = null;
argument = null;
context = null;
Log.d(TAG, "onDestroy >>>>>>>>>>>>>>>>>>>>>>>>\n");
}
}

View File

@ -1,202 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import android.view.View;
import android.widget.BaseAdapter;
import java.util.List;
import zuo.biao.library.interfaces.AdapterCallBack;
import zuo.biao.library.interfaces.OnReachViewBorderListener;
import zuo.biao.library.interfaces.OnStopLoadListener;
import zuo.biao.library.manager.HttpManager;
import zuo.biao.library.ui.xlistview.XListView;
import zuo.biao.library.ui.xlistview.XListView.IXListViewListener;
import zuo.biao.library.util.Log;
/**基础http获取列表的Activity
* @author Lemon
* @param <T> 数据模型(model/JavaBean)
* @param <BA> 管理XListView的Adapter
* @see #getListAsync(int)
* @see #onHttpResponse(int, String, Exception)
* @use extends BaseHttpListActivity 并在子类onCreate中lvBaseList.onRefresh();, 具体参考 .UserListFragment
*/
public abstract class BaseHttpListActivity<T, BA extends BaseAdapter> extends BaseListActivity<T, XListView, BA>
implements HttpManager.OnHttpResponseListener, IXListViewListener, OnStopLoadListener {
private static final String TAG = "BaseHttpListActivity";
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initView() {
super.initView();
setList((List<T>) null);//ListView需要设置adapter才能显示header和footer; setAdapter调不到子类方法
}
/**设置列表适配器
* @param callBack
*/
@SuppressWarnings("unchecked")
@Override
public void setList(AdapterCallBack<BA> callBack) {
super.setList(callBack);
boolean empty = adapter == null || adapter.isEmpty();
Log.d(TAG, "setList adapter empty = " + empty);
lvBaseList.showFooter(! empty);//放setAdapter中不行adapter!=null时没有调用setAdapter
if (adapter != null && adapter instanceof zuo.biao.library.base.BaseAdapter) {
((zuo.biao.library.base.BaseAdapter<T>) adapter).setOnReachViewBorderListener(
empty || lvBaseList.isFooterShowing() == false ? null : new OnReachViewBorderListener(){
@Override
public void onReach(int type, View v) {
if (type == TYPE_BOTTOM) {
lvBaseList.onLoadMore();
}
}
});
}
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initData() {
super.initData();
}
/**
* 将JSON串转为List已在非UI线程中
* *直接JSON.parseArray(json, getCacheClass());可以省去这个方法但由于可能json不完全符合parseArray条件所以还是要保留
* *比如json只有其中一部分能作为parseArray的字符串时必须先提取出这段字符串再parseArray
*/
public abstract List<T> parseArray(String json);
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
super.initEvent();
setOnStopLoadListener(this);
lvBaseList.setXListViewListener(this);
}
/*
* @param page -page作为requestCode
*/
@Override
public abstract void getListAsync(int page);
@Override
public void onStopRefresh() {
runUiThread(new Runnable() {
@Override
public void run() {
lvBaseList.stopRefresh();
}
});
}
@Override
public void onStopLoadMore(final boolean isHaveMore) {
runUiThread(new Runnable() {
@Override
public void run() {
lvBaseList.stopLoadMore(isHaveMore);
}
});
}
/**
* @param requestCode = -page {@link #getListAsync(int)}
* @param resultJson
* @param e
*/
@Override
public void onHttpResponse(final int requestCode, final String resultJson, final Exception e) {
runThread(TAG + "onHttpResponse", new Runnable() {
@Override
public void run() {
int page = 0;
if (requestCode > 0) {
Log.w(TAG, "requestCode > 0, 应该用BaseListFragment#getListAsync(int page)中的page的负数作为requestCode!");
} else {
page = - requestCode;
}
List<T> array = parseArray(resultJson);
if ((array == null || array.isEmpty()) && e != null) {
onLoadFailed(page, e);
} else {
onLoadSucceed(page, array);
}
}
});
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,201 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.List;
import zuo.biao.library.interfaces.AdapterCallBack;
import zuo.biao.library.interfaces.OnReachViewBorderListener;
import zuo.biao.library.interfaces.OnStopLoadListener;
import zuo.biao.library.manager.HttpManager;
import zuo.biao.library.ui.xlistview.XListView;
import zuo.biao.library.ui.xlistview.XListView.IXListViewListener;
import zuo.biao.library.util.Log;
import android.view.View;
import android.widget.BaseAdapter;
/**基础http获取列表的Fragment
* @author Lemon
* @param <T> 数据模型(model/JavaBean)
* @param <BA> 管理XListView的Adapter
* @see #getListAsync(int)
* @see #onHttpResponse(int, String, Exception)
* @use extends BaseHttpListFragment 并在子类onCreateView中lvBaseList.onRefresh();, 具体参考 .UserListFragment
*/
public abstract class BaseHttpListFragment<T, BA extends BaseAdapter> extends BaseListFragment<T, XListView, BA>
implements HttpManager.OnHttpResponseListener, IXListViewListener, OnStopLoadListener {
private static final String TAG = "BaseHttpListFragment";
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initView() {
super.initView();
setList((List<T>) null);//ListView需要设置adapter才能显示header和footer; setAdapter调不到子类方法
}
/**设置列表适配器
* @param callBack
*/
@SuppressWarnings("unchecked")
@Override
public void setList(AdapterCallBack<BA> callBack) {
super.setList(callBack);
boolean empty = adapter == null || adapter.isEmpty();
Log.d(TAG, "setList adapter empty = " + empty);
lvBaseList.showFooter(! empty);//放setAdapter中不行adapter!=null时没有调用setAdapter
if (adapter != null && adapter instanceof zuo.biao.library.base.BaseAdapter) {
((zuo.biao.library.base.BaseAdapter<T>) adapter).setOnReachViewBorderListener(
empty || lvBaseList.isFooterShowing() == false ? null : new OnReachViewBorderListener(){
@Override
public void onReach(int type, View v) {
if (type == TYPE_BOTTOM) {
lvBaseList.onLoadMore();
}
}
});
}
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initData() {
super.initData();
}
/**
* 将JSON串转为List已在非UI线程中
* *直接JSON.parseArray(json, getCacheClass());可以省去这个方法但由于可能json不完全符合parseArray条件所以还是要保留
* *比如json只有其中一部分能作为parseArray的字符串时必须先提取出这段字符串再parseArray
*/
public abstract List<T> parseArray(String json);
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
super.initEvent();
setOnStopLoadListener(this);
lvBaseList.setXListViewListener(this);
}
/*
* @param page -page作为requestCode
*/
@Override
public abstract void getListAsync(int page);
@Override
public void onStopRefresh() {
runUiThread(new Runnable() {
@Override
public void run() {
lvBaseList.stopRefresh();
}
});
}
@Override
public void onStopLoadMore(final boolean isHaveMore) {
runUiThread(new Runnable() {
@Override
public void run() {
lvBaseList.stopLoadMore(isHaveMore);
}
});
}
/**
* @param requestCode = -page {@link #getListAsync(int)}
* @param resultJson
* @param e
*/
@Override
public void onHttpResponse(final int requestCode, final String resultJson, final Exception e) {
runThread(TAG + "onHttpResponse", new Runnable() {
@Override
public void run() {
int page = 0;
if (requestCode > 0) {
Log.w(TAG, "requestCode > 0, 应该用BaseListFragment#getListAsync(int page)中的page的负数作为requestCode!");
} else {
page = - requestCode;
}
List<T> array = parseArray(resultJson);
if ((array == null || array.isEmpty()) && e != null) {
onLoadFailed(page, e);
} else {
onLoadSucceed(page, array);
}
}
});
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,443 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.AdapterCallBack;
import zuo.biao.library.interfaces.CacheCallBack;
import zuo.biao.library.interfaces.OnStopLoadListener;
import zuo.biao.library.manager.CacheManager;
import zuo.biao.library.manager.HttpManager;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.SettingUtil;
import zuo.biao.library.util.StringUtil;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
/**基础列表Activity
* @author Lemon
* @param <T> 数据模型(model/JavaBean)
* @param <LV> AbsListView的子类ListView,GridView等
* @param <BA> 管理LV的Adapter
* @see #lvBaseList
* @see #initCache
* @see #initView
* @see #getListAsync
* @see #onRefresh
* @use extends BaseListActivity 并在子类onCreate中调用onRefresh(...), 具体参考.DemoListActivity
* *缓存使用在initData前调用initCache(...), 具体参考 .DemoListActivity(onCreate方法内)
*/
public abstract class BaseListActivity<T, LV extends AbsListView, BA extends BaseAdapter> extends BaseActivity {
private static final String TAG = "BaseListActivity";
private OnStopLoadListener onStopLoadListener;
/**设置停止加载监听
* @param onStopLoadListener
*/
protected void setOnStopLoadListener(OnStopLoadListener onStopLoadListener) {
this.onStopLoadListener = onStopLoadListener;
}
private CacheCallBack<T> cacheCallBack;
/**初始化缓存
* @warn 在initData前使用才有效
* @param cacheCallBack
*/
protected void initCache(CacheCallBack<T> cacheCallBack) {
this.cacheCallBack = cacheCallBack;
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**
* 显示列表的ListView
* @warn 只使用lvBaseList为显示列表数据的AbsListView(ListView,GridView等)不要在子类中改变它
*/
protected LV lvBaseList;
/**
* 管理LV的Item的Adapter
*/
protected BA adapter;
/**
* 如果在子类中调用(即super.initView());则view必须含有initView中初始化用到的id且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
*/
@SuppressWarnings("unchecked")
@Override
public void initView() {// 必须调用
lvBaseList = (LV) findViewById(R.id.lvBaseList);
}
/**设置adapter
* @param adapter
*/
public void setAdapter(BA adapter) {
this.adapter = adapter;
lvBaseList.setAdapter(adapter);
}
/**显示列表已在UI线程中一般需求建议直接调用setList(List<T> l, AdapterCallBack<BA> callBack)
* @param list
*/
public abstract void setList(List<T> list);
/**显示列表已在UI线程中
* @param list
*/
public void setList(AdapterCallBack<BA> callBack) {
if (adapter == null) {
setAdapter(callBack.createAdapter());
}
callBack.refreshAdapter();
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private boolean isToSaveCache;
private boolean isToLoadCache;
@Override
public void initData() {// 必须调用
isToSaveCache = SettingUtil.cache && cacheCallBack != null && cacheCallBack.getCacheClass() != null;
isToLoadCache = isToSaveCache && StringUtil.isNotEmpty(cacheCallBack.getCacheGroup(), true);
}
/**
* 获取列表在非UI线程中
* @must 获取成功后调用onLoadSucceed
* @param page 在onLoadSucceed中传回来保证一致性
*/
public abstract void getListAsync(int page);
public void loadData(int page) {
loadData(page, isToLoadCache);
}
/**
* 数据列表
*/
private List<T> list;
/**
* 正在加载
*/
protected boolean isLoading = false;
/**
* 还有更多可加载数据
*/
protected boolean isHaveMore = true;
/**
* 加载页码每页对应一定数量的数据
*/
private int page;
private int loadCacheStart;
/**加载数据用getListAsync方法发请求获取数据
* @param page_
* @param isCache
*/
private void loadData(int page_, final boolean isCache) {
if (isLoading) {
Log.w(TAG, "loadData isLoading >> return;");
return;
}
isLoading = true;
isSucceed = false;
if (page_ <= HttpManager.PAGE_NUM_0) {
page_ = HttpManager.PAGE_NUM_0;
isHaveMore = true;
loadCacheStart = 0;//使用则可像网络正常情况下的重载不使用则在网络异常情况下不重载导致重载后加载数据下移
} else {
if (isHaveMore == false) {
stopLoadData(page_);
return;
}
loadCacheStart = list == null ? 0 : list.size();
}
this.page = page_;
Log.i(TAG, "loadData page_ = " + page_ + "; isCache = " + isCache
+ "; isHaveMore = " + isHaveMore + "; loadCacheStart = " + loadCacheStart);
runThread(TAG + "loadData", new Runnable() {
@Override
public void run() {
if (isCache == false) {//从网络获取数据
getListAsync(page);
} else {//从缓存获取数据
onLoadSucceed(page, CacheManager.getInstance().getList(cacheCallBack.getCacheClass()
, cacheCallBack.getCacheGroup(), loadCacheStart, cacheCallBack.getCacheCount()),
true);
if (page <= HttpManager.PAGE_NUM_0) {
isLoading = false;//stopLoadeData在其它线程isLoading = false;后这个线程里还是true
loadData(page, false);
}
}
}
});
}
/**停止加载数据
* isCache = false;
* @param page
*/
public synchronized void stopLoadData(int page) {
stopLoadData(page, false);
}
/**停止加载数据
* @param page
* @param isCache
*/
private synchronized void stopLoadData(int page, boolean isCache) {
Log.i(TAG, "stopLoadData isCache = " + isCache);
isLoading = false;
dismissProgressDialog();
if (isCache) {
Log.d(TAG, "stopLoadData isCache >> return;");
return;
}
if (onStopLoadListener == null) {
Log.w(TAG, "stopLoadData onStopLoadListener == null >> return;");
return;
}
onStopLoadListener.onStopRefresh();
if (page > HttpManager.PAGE_NUM_0) {
onStopLoadListener.onStopLoadMore(isHaveMore);
}
}
private boolean isSucceed = false;
/**处理列表
* @param page
* @param newList 新数据列表
* @param isCache
* @return
* @return
*/
public synchronized void handleList(int page, List<T> newList, boolean isCache) {
if (newList == null) {
newList = new ArrayList<T>();
}
isSucceed = ! newList.isEmpty();
Log.i(TAG, "\n\n<<<<<<<<<<<<<<<<<\n handleList newList.size = " + newList.size() + "; isCache = " + isCache
+ "; page = " + page + "; isSucceed = " + isSucceed);
if (page <= HttpManager.PAGE_NUM_0) {
Log.i(TAG, "handleList page <= HttpManager.PAGE_NUM_0 >>>> ");
saveCacheStart = 0;
list = new ArrayList<T>(newList);
if (isCache == false && list.isEmpty() == false) {
Log.i(TAG, "handleList isCache == false && list.isEmpty() == false >> isToLoadCache = false;");
isToLoadCache = false;
}
} else {
Log.i(TAG, "handleList page > HttpManager.PAGE_NUM_0 >>>> ");
if (list == null) {
list = new ArrayList<T>();
}
saveCacheStart = list.size();
isHaveMore = ! newList.isEmpty();
if (isHaveMore) {
list.addAll(newList);
}
}
Log.i(TAG, "handleList list.size = " + list.size() + "; isHaveMore = " + isHaveMore
+ "; isToLoadCache = " + isToLoadCache + "; saveCacheStart = " + saveCacheStart
+ "\n>>>>>>>>>>>>>>>>>>\n\n");
}
/**加载成功
* isCache = false;
* @param page
* @param newList
*/
public synchronized void onLoadSucceed(final int page, final List<T> newList) {
onLoadSucceed(page, newList, false);
}
/**加载成功
* @param page
* @param newList
* @param isCache newList是否为缓存
*/
private synchronized void onLoadSucceed(final int page, final List<T> newList, final boolean isCache) {
runThread(TAG + "onLoadSucceed", new Runnable() {
@Override
public void run() {
Log.i(TAG, "onLoadSucceed page = " + page + "; isCache = " + isCache + " >> handleList...");
handleList(page, newList, isCache);
runUiThread(new Runnable() {
@Override
public void run() {
stopLoadData(page, isCache);
setList(list);
}
});
if (isToSaveCache && isCache == false) {
saveCache(newList);
}
}
});
}
/**加载失败
* @param page
* @param e
*/
public synchronized void onLoadFailed(int page, Exception e) {
Log.e(TAG, "onLoadFailed page = " + page + "; e = " + (e == null ? null : e.getMessage()));
stopLoadData(page);
showShortToast(R.string.get_failed);
}
//缓存<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// /**
// * 获取缓存每页数量
// * @return > 0 缓存 : 不缓存
// */
// public int getCacheCount() {
// //让给服务器返回每页数量为count的数据不行的话在子类重写 Math.max(10, newList == null ? 0 : newList.size());
// return CacheManager.MAX_PAGE_SIZE;
// }
private int saveCacheStart;
/**保存缓存
* @param newList
*/
public synchronized void saveCache(List<T> newList) {
if (cacheCallBack == null || newList == null || newList.isEmpty()) {
Log.e(TAG, "saveCache cacheCallBack == null || newList == null || newList.isEmpty() >> return;");
return;
}
LinkedHashMap<String, T> map = new LinkedHashMap<String, T>();
for (T data : newList) {
if (data != null) {
map.put(cacheCallBack.getCacheId(data), data);//map.put(null, data);不会崩溃
}
}
CacheManager.getInstance().saveList(cacheCallBack.getCacheClass(), cacheCallBack.getCacheGroup()
, map, saveCacheStart, cacheCallBack.getCacheCount());
}
//缓存>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {
}
/**刷新从头加载
* @must 在子类onCreate中调用建议放在最后
*/
public void onRefresh() {
loadData(HttpManager.PAGE_NUM_0);
}
/**加载更多
*/
public void onLoadMore() {
if (isSucceed == false && page <= HttpManager.PAGE_NUM_0) {
Log.w(TAG, "onLoadMore isSucceed == false && page <= HttpManager.PAGE_NUM_0 >> return;");
return;
}
loadData(page + (isSucceed ? 1 : 0));
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
protected void onDestroy() {
isLoading = false;
isHaveMore = false;
isToSaveCache = false;
isToLoadCache = false;
super.onDestroy();
lvBaseList = null;
list = null;
onStopLoadListener = null;
cacheCallBack = null;
}
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,510 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.AdapterCallBack;
import zuo.biao.library.interfaces.CacheCallBack;
import zuo.biao.library.interfaces.OnStopLoadListener;
import zuo.biao.library.manager.CacheManager;
import zuo.biao.library.manager.HttpManager;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.SettingUtil;
import zuo.biao.library.util.StringUtil;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
/**基础列表Activity
* @author Lemon
* @param <T> 数据模型(model/JavaBean)
* @param <LV> AbsListView的子类ListView,GridView等
* @param <BA> 管理LV的Adapter
* @see #onCreateView
* @see #setContentView
* @see #lvBaseList
* @see #initCache
* @see #initView
* @see #getListAsync
* @see #onRefresh
* @use extends BaseListFragment 并在子类onCreate中调用onRefresh(...), 具体参考.DemoListFragment
* *缓存使用在initData前调用initCache(...), 具体参考 .UserListFragment(onCreate方法内)
*/
public abstract class BaseListFragment<T, LV extends AbsListView, BA extends BaseAdapter> extends BaseFragment {
private static final String TAG = "BaseListFragment";
private OnStopLoadListener onStopLoadListener;
/**设置停止加载监听
* @param onStopLoadListener
*/
protected void setOnStopLoadListener(OnStopLoadListener onStopLoadListener) {
this.onStopLoadListener = onStopLoadListener;
}
private CacheCallBack<T> cacheCallBack;
/**初始化缓存
* @warn 在initData前使用才有效
* @param cacheCallBack
*/
protected void initCache(CacheCallBack<T> cacheCallBack) {
this.cacheCallBack = cacheCallBack;
}
/**
* @param inflater
* @param container
* @param savedInstanceState
* @return
* @must 1.不要在子类重复这个类中onCreateView中的代码;
* 2.在子类onCreateView中super.onCreateView(inflater, container, savedInstanceState);
* initView();initData();initEvent(); return view;
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return onCreateView(inflater, container, savedInstanceState, 0);
}
/**
* @param inflater
* @param container
* @param savedInstanceState
* @param layoutResID fragment全局视图view的布局资源id默认值为R.layout.base_http_list_fragment
* @return
* @must 1.不要在子类重复这个类中onCreateView中的代码;
* 2.在子类onCreateView中super.onCreateView(inflater, container, savedInstanceState, layoutResID);
* initView();initData();initEvent(); return view;
*/
public final View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState, int layoutResID) {
//类相关初始化必须使用<<<<<<<<<<<<<<<<<<
super.onCreateView(inflater, container, savedInstanceState);
//调用这个类的setContentView而崩溃 super.setContentView(layoutResID <= 0 ? R.layout.base_tab_activity : layoutResID);
view = inflater.inflate(layoutResID <= 0 ? R.layout.base_list_fragment : layoutResID, container, false);
//类相关初始化必须使用>>>>>>>>>>>>>>>>
return view;
}
//防止子类中setContentView <<<<<<<<<<<<<<<<<<<<<<<<
/**
* @warn 不支持setContentView传界面布局请使用onCreateView(Bundle savedInstanceState, int layoutResID)等方法
*/
@Override
public final void setContentView(int layoutResID) {
setContentView(null);
}
/**
* @warn 不支持setContentView传界面布局请使用onCreateView(Bundle savedInstanceState, int layoutResID)等方法
*/
@Override
public final void setContentView(View view) {
setContentView(null, null);
}
/**
* @warn 不支持setContentView传界面布局请使用onCreateView(Bundle savedInstanceState, int layoutResID)等方法
*/
@Override
public final void setContentView(View view, LayoutParams params) {
throw new UnsupportedOperationException(TAG + "不支持setContentView传界面布局请使用onCreateView(" +
"LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, int layoutResID)等方法");
}
//防止子类中setContentView >>>>>>>>>>>>>>>>>>>>>>>>>
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**
* 显示列表的ListView
* @warn 只使用lvBaseList为显示列表数据的AbsListView(ListView,GridView等)不要在子类中改变它
*/
protected LV lvBaseList;
/**
* 管理LV的Item的Adapter
*/
protected BA adapter;
/**
* 如果在子类中调用(即super.initView());则view必须含有initView中初始化用到的id且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
*/
@SuppressWarnings("unchecked")
@Override
public void initView() {// 必须调用
lvBaseList = (LV) findViewById(R.id.lvBaseList);
}
/**设置adapter
* @param adapter
*/
public void setAdapter(BA adapter) {
this.adapter = adapter;
lvBaseList.setAdapter(adapter);
}
/**显示列表已在UI线程中一般需求建议直接调用setList(List<T> l, AdapterCallBack<BA> callBack)
* @param list
*/
public abstract void setList(List<T> list);
/**显示列表已在UI线程中
* @param callBack
*/
public void setList(AdapterCallBack<BA> callBack) {
if (adapter == null) {
setAdapter(callBack.createAdapter());
}
callBack.refreshAdapter();
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private boolean isToSaveCache;
private boolean isToLoadCache;
@Override
public void initData() {// 必须调用
isToSaveCache = SettingUtil.cache && cacheCallBack != null && cacheCallBack.getCacheClass() != null;
isToLoadCache = isToSaveCache && StringUtil.isNotEmpty(cacheCallBack.getCacheGroup(), true);
}
/**
* 获取列表在非UI线程中
* @must 获取成功后调用onLoadSucceed
* @param page 在onLoadSucceed中传回来保证一致性
*/
public abstract void getListAsync(int page);
public void loadData(int page) {
loadData(page, isToLoadCache);
}
/**
* 数据列表
*/
private List<T> list;
/**
* 正在加载
*/
protected boolean isLoading = false;
/**
* 还有更多可加载数据
*/
protected boolean isHaveMore = true;
/**
* 加载页码每页对应一定数量的数据
*/
private int page;
private int loadCacheStart;
/**加载数据用getListAsync方法发请求获取数据
* @param page_
* @param isCache
*/
private void loadData(int page_, final boolean isCache) {
if (isLoading) {
Log.w(TAG, "loadData isLoading >> return;");
return;
}
isLoading = true;
isSucceed = false;
if (page_ <= HttpManager.PAGE_NUM_0) {
page_ = HttpManager.PAGE_NUM_0;
isHaveMore = true;
loadCacheStart = 0;//使用则可像网络正常情况下的重载不使用则在网络异常情况下不重载导致重载后加载数据下移
} else {
if (isHaveMore == false) {
stopLoadData(page_);
return;
}
loadCacheStart = list == null ? 0 : list.size();
}
this.page = page_;
Log.i(TAG, "loadData page_ = " + page_ + "; isCache = " + isCache
+ "; isHaveMore = " + isHaveMore + "; loadCacheStart = " + loadCacheStart);
runThread(TAG + "loadData", new Runnable() {
@Override
public void run() {
if (isCache == false) {//从网络获取数据
getListAsync(page);
} else {//从缓存获取数据
onLoadSucceed(page, CacheManager.getInstance().getList(cacheCallBack.getCacheClass()
, cacheCallBack.getCacheGroup(), loadCacheStart, cacheCallBack.getCacheCount()),
true);
if (page <= HttpManager.PAGE_NUM_0) {
isLoading = false;//stopLoadeData在其它线程isLoading = false;后这个线程里还是true
loadData(page, false);
}
}
}
});
}
/**停止加载数据
* isCache = false;
* @param page
*/
public synchronized void stopLoadData(int page) {
stopLoadData(page, false);
}
/**停止加载数据
* @param page
* @param isCache
*/
private synchronized void stopLoadData(int page, boolean isCache) {
Log.i(TAG, "stopLoadData isCache = " + isCache);
isLoading = false;
dismissProgressDialog();
if (isCache) {
Log.d(TAG, "stopLoadData isCache >> return;");
return;
}
if (onStopLoadListener == null) {
Log.w(TAG, "stopLoadData onStopLoadListener == null >> return;");
return;
}
onStopLoadListener.onStopRefresh();
if (page > HttpManager.PAGE_NUM_0) {
onStopLoadListener.onStopLoadMore(isHaveMore);
}
}
private boolean isSucceed = false;
/**处理列表
* @param page
* @param newList 新数据列表
* @param isCache
* @return
* @return
*/
public synchronized void handleList(int page, List<T> newList, boolean isCache) {
if (newList == null) {
newList = new ArrayList<T>();
}
isSucceed = ! newList.isEmpty();
Log.i(TAG, "\n\n<<<<<<<<<<<<<<<<<\n handleList newList.size = " + newList.size() + "; isCache = " + isCache
+ "; page = " + page + "; isSucceed = " + isSucceed);
if (page <= HttpManager.PAGE_NUM_0) {
Log.i(TAG, "handleList page <= HttpManager.PAGE_NUM_0 >>>> ");
saveCacheStart = 0;
list = new ArrayList<T>(newList);
if (isCache == false && list.isEmpty() == false) {
Log.i(TAG, "handleList isCache == false && list.isEmpty() == false >> isToLoadCache = false;");
isToLoadCache = false;
}
} else {
Log.i(TAG, "handleList page > HttpManager.PAGE_NUM_0 >>>> ");
if (list == null) {
list = new ArrayList<T>();
}
saveCacheStart = list.size();
isHaveMore = ! newList.isEmpty();
if (isHaveMore) {
list.addAll(newList);
}
}
Log.i(TAG, "handleList list.size = " + list.size() + "; isHaveMore = " + isHaveMore
+ "; isToLoadCache = " + isToLoadCache + "; saveCacheStart = " + saveCacheStart
+ "\n>>>>>>>>>>>>>>>>>>\n\n");
}
/**加载成功
* isCache = false;
* @param page
* @param newList
*/
public synchronized void onLoadSucceed(final int page, final List<T> newList) {
onLoadSucceed(page, newList, false);
}
/**加载成功
* @param page
* @param newList
* @param isCache newList是否为缓存
*/
private synchronized void onLoadSucceed(final int page, final List<T> newList, final boolean isCache) {
runThread(TAG + "onLoadSucceed", new Runnable() {
@Override
public void run() {
Log.i(TAG, "onLoadSucceed page = " + page + "; isCache = " + isCache + " >> handleList...");
handleList(page, newList, isCache);
runUiThread(new Runnable() {
@Override
public void run() {
stopLoadData(page, isCache);
setList(list);
}
});
if (isToSaveCache && isCache == false) {
saveCache(newList);
}
}
});
}
/**加载失败
* @param page
* @param e
*/
public synchronized void onLoadFailed(int page, Exception e) {
Log.e(TAG, "onLoadFailed page = " + page + "; e = " + (e == null ? null : e.getMessage()));
stopLoadData(page);
showShortToast(R.string.get_failed);
}
//缓存<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// /**
// * 获取缓存每页数量
// * @return > 0 缓存 : 不缓存
// */
// public int getCacheCount() {
// //让给服务器返回每页数量为count的数据不行的话在子类重写 Math.max(10, newList == null ? 0 : newList.size());
// return CacheManager.MAX_PAGE_SIZE;
// }
private int saveCacheStart;
/**保存缓存
* @param newList
*/
public synchronized void saveCache(List<T> newList) {
if (cacheCallBack == null || newList == null || newList.isEmpty()) {
Log.e(TAG, "saveCache cacheCallBack == null || newList == null || newList.isEmpty() >> return;");
return;
}
LinkedHashMap<String, T> map = new LinkedHashMap<String, T>();
for (T data : newList) {
if (data != null) {
map.put(cacheCallBack.getCacheId(data), data);//map.put(null, data);不会崩溃
}
}
CacheManager.getInstance().saveList(cacheCallBack.getCacheClass(), cacheCallBack.getCacheGroup()
, map, saveCacheStart, cacheCallBack.getCacheCount());
}
//缓存>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {
}
/**刷新从头加载
* @must 在子类onCreate中调用建议放在最后
*/
public void onRefresh() {
loadData(HttpManager.PAGE_NUM_0);
}
/**加载更多
*/
public void onLoadMore() {
if (isSucceed == false && page <= HttpManager.PAGE_NUM_0) {
Log.w(TAG, "onLoadMore isSucceed == false && page <= HttpManager.PAGE_NUM_0 >> return;");
return;
}
loadData(page + (isSucceed ? 1 : 0));
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void onDestroy() {
isLoading = false;
isHaveMore = false;
isToSaveCache = false;
isToLoadCache = false;
super.onDestroy();
lvBaseList = null;
list = null;
onStopLoadListener = null;
cacheCallBack = null;
}
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,58 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.io.Serializable;
/**基础Model继承它可以省去部分代码也可以不继承
* *isCorrect可以用于BaseModel子类的数据校验
* *implements Serializable 是为了网络传输字节流转换
* @author Lemon
* @use extends BaseModel
*/
@SuppressWarnings("serial")
public abstract class BaseModel implements Serializable {
public long id;
//对子类不起作用
// /**默认构造方法JSON等解析时必须要有
// */
// public BaseModel() {
// }
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
/**数据正确性校验
* @param data
* @return
*/
public static boolean isCorrect(BaseModel data) {
return data != null && data.isCorrect();
}
/**数据正确性校验
* @return
*/
protected abstract boolean isCorrect();//public导致JSON.toJSONString会添加correct字段
}

View File

@ -1,496 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.OnBottomDragListener;
import zuo.biao.library.interfaces.ViewPresenter;
import zuo.biao.library.ui.TopTabView;
import zuo.biao.library.ui.TopTabView.OnTabSelectedListener;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
/**基础带标签的FragmentActivity
* @author Lemon
* @see #onCreate
* @see #setContentView
* @use extends BaseTabActivity, 具体参考.DemoTabActivity
* @must 在子类onCreate中调用initView();initData();initEvent();
*/
public abstract class BaseTabActivity extends BaseActivity implements ViewPresenter
, OnClickListener, OnTabSelectedListener {
private static final String TAG = "BaseTabActivity";
/**
* @param savedInstanceState
* @return
* @must 1.不要在子类重复这个类中onCreate中的代码;
* 2.在子类onCreate中super.onCreate(savedInstanceState);
* initView();initData();initEvent();
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
onCreate(savedInstanceState, 0);
}
/**
* @param savedInstanceState
* @param layoutResID activity全局视图view的布局资源id默认值为R.layout.base_tab_activity
* @return
* @must 1.不要在子类重复这个类中onCreate中的代码;
* 2.在子类onCreate中super.onCreate(savedInstanceState, layoutResID);
* initView();initData();initEvent();
*/
protected final void onCreate(Bundle savedInstanceState, int layoutResID) {
onCreate(savedInstanceState, layoutResID, null);
}
/**
* @param savedInstanceState
* @param listener this - 滑动返回 ; null - 没有滑动返回
* @return
* @must 1.不要在子类重复这个类中onCreate中的代码;
* 2.在子类onCreate中super.onCreate(savedInstanceState, listener);
* initView();initData();initEvent();
*/
protected final void onCreate(Bundle savedInstanceState, OnBottomDragListener listener) {
onCreate(savedInstanceState, 0, listener);
}
/**
* @param savedInstanceState
* @param layoutResID activity全局视图view的布局资源id <= 0 ? R.layout.base_tab_activity : layoutResID
* @param listener == null ? 没有滑动返回 : 滑动返回
* @return
* @must 1.不要在子类重复这个类中onCreate中的代码;
* 2.在子类onCreate中super.onCreate(savedInstanceState, layoutResID, listener);
* initView();initData();initEvent();
*/
protected final void onCreate(Bundle savedInstanceState, int layoutResID, OnBottomDragListener listener) {
super.onCreate(savedInstanceState);
super.setContentView(layoutResID <= 0 ? R.layout.base_tab_activity : layoutResID, listener);
}
// //BaseActivity重写setContentView后这个方法一定会被调用final有无都会导致崩溃去掉throw Exception也会导致contentView为null而崩溃
// //防止子类中setContentView <<<<<<<<<<<<<<<<<<<<<<<<
// /**
// * @warn 不支持setContentView传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法
// */
// @Override
// public final void setContentView(int layoutResID) {
// setContentView(null);
// }
// /**
// * @warn 不支持setContentView传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法
// */
// @Override
// public final void setContentView(View view) {
// setContentView(null, null);
// }
// /**
// * @warn 不支持setContentView传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法
// */
// @Override
// public final void setContentView(View view, LayoutParams params) {
// throw new UnsupportedOperationException(TAG + "不支持setContentView" +
// "传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法");
// }
// //防止子类中setContentView >>>>>>>>>>>>>>>>>>>>>>>>>
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Nullable
private TextView tvBaseTabTitle;
@Nullable
private View ivBaseTabReturn;
@Nullable
private TextView tvBaseTabReturn;
@Nullable
private TextView tvBaseTabForward;
@Nullable
private ViewGroup llBaseTabTopRightButtonContainer;
private ViewGroup llBaseTabTabContainer;
/**
* 如果在子类中调用(即super.initView());则view必须含有initView中初始化用到的id(@Nullable标记)且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
*/
@Override
public void initView() {// 必须调用
tvBaseTabTitle = (TextView) findViewById(R.id.tvBaseTabTitle);
ivBaseTabReturn = findViewById(R.id.ivBaseTabReturn);
tvBaseTabReturn = (TextView) findViewById(R.id.tvBaseTabReturn);
llBaseTabTopRightButtonContainer = (ViewGroup)
findViewById(R.id.llBaseTabTopRightButtonContainer);
llBaseTabTabContainer = (ViewGroup) findViewById(R.id.llBaseTabTabContainer);
}
/**
* == true >> 每次点击相应tab都加载调用getFragment方法重新对点击的tab对应的fragment赋值
* 如果不希望重载可以setOnTabSelectedListener然后在onTabSelected内重写点击tab事件
*/
protected boolean needReload = false;
/**
* 当前显示的tab所在位置对应fragment所在位置
*/
protected int currentPosition = 0;
/**选择下一个tab和fragment
*/
public void selectNext() {
select((getCurrentPosition() + 1) % getCount());
}
/**选择tab和fragment
* @param position
*/
public void select(int position) {
topTabView.select(position);
}
/**选择并显示fragment
* @param position
*/
public void selectFragment(int position) {
if (fragments == null || fragments.length != getCount()) {
if (fragments != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
for (int i = 0; i < fragments.length; i++) {
fragmentTransaction.remove(fragments[i]);
}
fragmentTransaction.commit();
}
fragments = new Fragment[getCount()];
}
if (currentPosition == position) {
if (needReload == false && fragments[position] != null && fragments[position].isVisible()) {
Log.w(TAG, "selectFragment currentPosition == position" +
" >> fragments[position] != null && fragments[position].isVisible()" +
" >> return; ");
return;
}
}
if (needReload || fragments[position] == null) {
fragments[position] = getFragment(position);
}
//全局的fragmentTransaction因为already committed 崩溃
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.hide(fragments[currentPosition]);
if (fragments[position].isAdded() == false) {
fragmentTransaction.add(R.id.flBaseTabFragmentContainer, fragments[position]);
}
fragmentTransaction.show(fragments[position]).commit();
this.currentPosition = position;
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected TopTabView topTabView;
private Fragment[] fragments;
@Override
public void initData() {// 必须调用
if (tvBaseTabTitle != null) {
tvBaseTabTitle.setVisibility(StringUtil.isNotEmpty(getTitleName(), true) ? View.VISIBLE : View.GONE);
tvBaseTabTitle.setText(StringUtil.getTrimedString(getTitleName()));
}
//返回按钮<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
String returnName = getReturnName();
if (returnName == null) {
if (ivBaseTabReturn != null) {
ivBaseTabReturn.setVisibility(View.GONE);
}
if (tvBaseTabReturn != null) {
tvBaseTabReturn.setVisibility(View.GONE);
}
} else {
boolean isReturnButtonHasName = StringUtil.isNotEmpty(returnName, true);
if (ivBaseTabReturn != null) {
ivBaseTabReturn.setVisibility(isReturnButtonHasName ? View.GONE : View.VISIBLE);
}
if (tvBaseTabReturn != null) {
tvBaseTabReturn.setVisibility(isReturnButtonHasName ? View.VISIBLE : View.GONE);
tvBaseTabReturn.setText(StringUtil.getTrimedString(returnName));
}
}
//返回按钮>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//前进按钮<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
String forwardName = getForwardName();
if (StringUtil.isNotEmpty(forwardName, true)) {
tvBaseTabForward = addTopRightButton(newTopRightTextView(context, StringUtil.getTrimedString(forwardName)));
}
if (llBaseTabTopRightButtonContainer != null
&& topRightButtonList != null && topRightButtonList.size() > 0) {
llBaseTabTopRightButtonContainer.removeAllViews();
for (View btn : topRightButtonList) {
llBaseTabTopRightButtonContainer.addView(btn);
}
}
//前进按钮>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//tab<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
topTabView = new TopTabView(context, getResources());
llBaseTabTabContainer.removeAllViews();
llBaseTabTabContainer.addView(topTabView.createView(getLayoutInflater()));
topTabView.setCurrentPosition(currentPosition);
topTabView.bindView(getTabNames());
//tab>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// fragmentActivity子界面初始化<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
selectFragment(currentPosition);
// fragmentActivity子界面初始化>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
/**获取导航栏标题名
* @return null - View.GONE; "" - <; "xxx" - "xxx"
*/
@Override
@Nullable
public abstract String getTitleName();
/**获取导航栏标题名
* @return null - View.GONE; "" - <; "xxx" - "xxx"
*/
@Override
@Nullable
public abstract String getReturnName();
//top right button <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**获取导航栏标题名
* @return null - View.GONE; "" - View.GONE; "xxx" - "xxx"
*/
@Override
@Nullable
public abstract String getForwardName();
@Nullable
private List<View> topRightButtonList = new ArrayList<View>();
/**添加右上方导航栏按钮
* @warn 在initData前使用才有效
* @param topRightButton 不会在这个类设置监听,需要自行设置
*/
public <V extends View> V addTopRightButton(V topRightButton) {
if (topRightButton != null) {
topRightButtonList.add(topRightButton);
}
return topRightButton;
}
/**新建右上方导航栏按钮
* @param context
* @param drawable
* @return
*/
public ImageView newTopRightImageView(Context context, int drawable) {
return newTopRightImageView(context, getResources().getDrawable(drawable));
}
/**新建右上方导航栏按钮
* @param context
* @param drawable
* @return
*/
@SuppressLint({ "NewApi", "InflateParams" })
public ImageView newTopRightImageView(Context context, Drawable drawable) {
ImageView topRightButton = (ImageView) LayoutInflater.from(context).inflate(R.layout.top_right_iv, null);
topRightButton.setImageDrawable(drawable);
return topRightButton;
}
/**新建右上方导航栏按钮
* @param context
* @param name
* @return
*/
@SuppressLint({ "NewApi", "InflateParams" })
public TextView newTopRightTextView(Context context, String name) {
TextView topRightButton = (TextView) LayoutInflater.from(context).inflate(R.layout.top_right_tv, null);
topRightButton.setText(name);
return topRightButton;
}
//top right button >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**获取标签名称数组
* @return
*/
protected abstract String[] getTabNames();
/**获取新的Fragment
* @param position
* @return
*/
protected abstract Fragment getFragment(int position);
/**获取Tab(或Fragment)的数量
* @return
*/
public int getCount() {
return topTabView == null ? 0 : topTabView.getCount();
}
/**获取当前Tab(或Fragment)的位置
* @return
*/
public int getCurrentPosition() {
return currentPosition;
}
public TextView getCurrentTab() {
return topTabView == null ? null : topTabView.getCurrentTab();
};
public Fragment getCurrentFragment() {
return fragments[currentPosition];
};
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
if (ivBaseTabReturn != null) {
ivBaseTabReturn.setOnClickListener(this);
}
if (tvBaseTabReturn != null) {
tvBaseTabReturn.setOnClickListener(this);
}
if (tvBaseTabForward != null) {
tvBaseTabForward.setOnClickListener(new OnClickListener() {//没有id
@Override
public void onClick(View v) {
onForwardClick(v);
}
});
}
topTabView.setOnTabSelectedListener(this);
}
@Override
public void onTabSelected(TextView tvTab, int position, int id) {
selectFragment(position);
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void onClick(View v) {
if (v.getId() == R.id.ivBaseTabReturn || v.getId() == R.id.tvBaseTabReturn) {
finish();
}
}
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
protected void onDestroy() {
super.onDestroy();
topTabView = null;
fragments = null;
ivBaseTabReturn = null;
tvBaseTabReturn = null;
llBaseTabTopRightButtonContainer = null;
llBaseTabTabContainer = null;
tvBaseTabTitle = null;
currentPosition = 0;
needReload = false;
topRightButtonList = null;
}
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,450 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.ViewPresenter;
import zuo.biao.library.ui.TopTabView;
import zuo.biao.library.ui.TopTabView.OnTabSelectedListener;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.TextView;
/**基础带标签的Fragment
* @author Lemon
* @see #onCreateView
* @see #setContentView
* @use extends BaseTabFragment, 具体参考.DemoTabFragment
* @must 在子类onCreateView中调用initView();initData();initEvent();
*/
public abstract class BaseTabFragment extends BaseFragment implements ViewPresenter
, OnClickListener, OnTabSelectedListener {
private static final String TAG = "BaseTabFragment";
/**
* FragmentManager
*/
protected FragmentManager fragmentManager = null;
/**
* @warn 如果在子类中super.initView();则view必须含有initView中初始化用到的id且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
* @param inflater
* @param container
* @param savedInstanceState
* @return
* @must 1.不要在子类重复这个类中onCreateView中的代码;
* 2.在子类onCreateView中super.onCreateView(inflater, container, savedInstanceState);
* initView();initData();initEvent(); return view;
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return onCreateView(inflater, container, savedInstanceState, 0);
}
/**
* @param inflater
* @param container
* @param savedInstanceState
* @param layoutResID fragment全局视图view的布局资源id <= 0 ? R.layout.base_tab_activity : layoutResID
* @return
* @must 1.不要在子类重复这个类中onCreateView中的代码;
* 2.在子类onCreateView中super.onCreateView(inflater, container, savedInstanceState, layoutResID);
* initView();initData();initEvent(); return view;
*/
public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState
, int layoutResID) {
//类相关初始化必须使用<<<<<<<<<<<<<<<<<<
super.onCreateView(inflater, container, savedInstanceState);
//调用这个类的setContentView而崩溃 super.setContentView(layoutResID <= 0 ? R.layout.base_tab_activity : layoutResID);
view = inflater.inflate(layoutResID <= 0 ? R.layout.base_tab_activity : layoutResID, container, false);
//类相关初始化必须使用>>>>>>>>>>>>>>>>
fragmentManager = context.getSupportFragmentManager();
return view;
}
//防止子类中setContentView <<<<<<<<<<<<<<<<<<<<<<<<
/**
* @warn 不支持setContentView传界面布局请使用onCreateView(Bundle savedInstanceState, int layoutResID)等方法
*/
@Override
public void setContentView(int layoutResID) {
setContentView(null);
}
/**
* @warn 不支持setContentView传界面布局请使用onCreateView(Bundle savedInstanceState, int layoutResID)等方法
*/
@Override
public void setContentView(View view) {
setContentView(null, null);
}
/**
* @warn 不支持setContentView传界面布局请使用onCreateView(Bundle savedInstanceState, int layoutResID)等方法
*/
@Override
public void setContentView(View view, LayoutParams params) {
throw new UnsupportedOperationException(TAG + "不支持setContentView传界面布局请使用onCreateView(" +
"LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, int layoutResID)等方法");
}
//防止子类中setContentView >>>>>>>>>>>>>>>>>>>>>>>>>
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Nullable
private TextView tvBaseTabTitle;
@Nullable
private View ivBaseTabReturn;
@Nullable
private TextView tvBaseTabReturn;
@Nullable
private ViewGroup llBaseTabTopRightButtonContainer;
private ViewGroup llBaseTabTabContainer;
/**
* 如果在子类中调用(即super.initView());则view必须含有initView中初始化用到的id(@Nullable标记)且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
*/
@Override
public void initView() {// 必须调用
tvBaseTabTitle = (TextView) findViewById(R.id.tvBaseTabTitle);
ivBaseTabReturn = findViewById(R.id.ivBaseTabReturn);
tvBaseTabReturn = (TextView) findViewById(R.id.tvBaseTabReturn);
llBaseTabTopRightButtonContainer = (ViewGroup)
findViewById(R.id.llBaseTabTopRightButtonContainer);
llBaseTabTabContainer = (ViewGroup) findViewById(R.id.llBaseTabTabContainer);
}
/**
* == true >> 每次点击相应tab都加载调用getFragment方法重新对点击的tab对应的fragment赋值
* 如果不希望重载可以setOnTabSelectedListener然后在onTabSelected内重写点击tab事件
*/
protected boolean needReload = false;
/**
* 当前显示的tab所在位置对应fragment所在位置
*/
protected int currentPosition = 0;
/**选择下一个tab和fragment
*/
public void selectNext() {
select((getCurrentPosition() + 1) % getCount());
}
/**选择tab和fragment
* @param position
*/
public void select(int position) {
topTabView.select(position);
}
/**选择并显示fragment
* @param position
*/
public void selectFragment(int position) {
if (currentPosition == position) {
if (needReload == false && fragments[position] != null && fragments[position].isVisible()) {
Log.w(TAG, "selectFragment currentPosition == position" +
" >> fragments[position] != null && fragments[position].isVisible()" +
" >> return; ");
return;
}
}
if (needReload || fragments[position] == null) {
fragments[position] = getFragment(position);
}
//全局的fragmentTransaction因为already committed 崩溃
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.hide(fragments[currentPosition]);
if (fragments[position].isAdded() == false) {
fragmentTransaction.add(R.id.flBaseTabFragmentContainer, fragments[position]);
}
fragmentTransaction.show(fragments[position]).commit();
this.currentPosition = position;
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private String topReturnButtonName;
protected TopTabView topTabView;
private Fragment[] fragments;
@Override
public void initData() {// 必须调用
if (tvBaseTabTitle != null) {
tvBaseTabTitle.setVisibility(StringUtil.isNotEmpty(getTitleName(), true) ? View.VISIBLE : View.GONE);
tvBaseTabTitle.setText(StringUtil.getTrimedString(getTitleName()));
}
topReturnButtonName = getReturnName();
if (topReturnButtonName == null) {
if (ivBaseTabReturn != null) {
ivBaseTabReturn.setVisibility(View.GONE);
}
if (tvBaseTabReturn != null) {
tvBaseTabReturn.setVisibility(View.GONE);
}
} else {
boolean isReturnButtonHasName = StringUtil.isNotEmpty(topReturnButtonName, true);
if (ivBaseTabReturn != null) {
ivBaseTabReturn.setVisibility(isReturnButtonHasName ? View.GONE : View.VISIBLE);
}
if (tvBaseTabReturn != null) {
tvBaseTabReturn.setVisibility(isReturnButtonHasName ? View.VISIBLE : View.GONE);
tvBaseTabReturn.setText(StringUtil.getTrimedString(topReturnButtonName));
}
}
if (llBaseTabTopRightButtonContainer != null
&& topRightButtonList != null && topRightButtonList.size() > 0) {
llBaseTabTopRightButtonContainer.removeAllViews();
for (View btn : topRightButtonList) {
llBaseTabTopRightButtonContainer.addView(btn);
}
}
topTabView = new TopTabView(context, getResources());
llBaseTabTabContainer.removeAllViews();
llBaseTabTabContainer.addView(topTabView.createView(context.getLayoutInflater()));
topTabView.setCurrentPosition(currentPosition);
topTabView.bindView(getTabNames());
// fragmentActivity子界面初始化<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
fragments = new Fragment[getCount()];
selectFragment(currentPosition);
// fragmentActivity子界面初始化>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
//top right button <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
@Nullable
public final String getForwardName() {
return null;
}
@Nullable
private List<View> topRightButtonList = new ArrayList<View>();
/**添加右上方导航栏按钮
* @warn 在initData前使用才有效
* @param topRightButton 不会在这个类设置监听,需要自行设置
*/
public <V extends View> V addTopRightButton(V topRightButton) {
if (topRightButton != null) {
topRightButtonList.add(topRightButton);
}
return topRightButton;
}
/**新建右上方导航栏按钮
* @param context
* @param drawable
* @return
*/
public ImageView newTopRightImageView(Context context, int drawable) {
return newTopRightImageView(context, getResources().getDrawable(drawable));
}
/**新建右上方导航栏按钮
* @param context
* @param drawable
* @return
*/
@SuppressLint({ "NewApi", "InflateParams" })
public ImageView newTopRightImageView(Context context, Drawable drawable) {
ImageView topRightButton = (ImageView) LayoutInflater.from(context).inflate(R.layout.top_right_iv, null);
topRightButton.setImageDrawable(drawable);
return topRightButton;
}
/**新建右上方导航栏按钮
* @param context
* @param name
* @return
*/
@SuppressLint({ "NewApi", "InflateParams" })
public TextView newTopRightTextView(Context context, String name) {
TextView topRightButton = (TextView) LayoutInflater.from(context).inflate(R.layout.top_right_tv, null);
topRightButton.setText(name);
return topRightButton;
}
//top right button >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**获取标签名称数组
* @return
*/
protected abstract String[] getTabNames();
/**获取新的Fragment
* @param position
* @return
*/
protected abstract Fragment getFragment(int position);
/**获取Tab(或Fragment)的数量
* @return
*/
public int getCount() {
return topTabView == null ? 0 : topTabView.getCount();
}
/**获取当前Tab(或Fragment)的位置
* @return
*/
public int getCurrentPosition() {
return currentPosition;
}
public TextView getCurrentTab() {
return topTabView == null ? null : topTabView.getCurrentTab();
};
public Fragment getCurrentFragment() {
return fragments[currentPosition];
};
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
if (ivBaseTabReturn != null) {
ivBaseTabReturn.setOnClickListener(this);
}
if (tvBaseTabReturn != null) {
tvBaseTabReturn.setOnClickListener(this);
}
topTabView.setOnTabSelectedListener(this);
}
@Override
public void onTabSelected(TextView tvTab, int position, int id) {
selectFragment(position);
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void onClick(View v) {
if (v.getId() == R.id.ivBaseTabReturn || v.getId() == R.id.tvBaseTabReturn) {
context.finish();
}
}
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void onDestroy() {
super.onDestroy();
topTabView = null;
fragments = null;
ivBaseTabReturn = null;
tvBaseTabReturn = null;
llBaseTabTopRightButtonContainer = null;
llBaseTabTabContainer = null;
tvBaseTabTitle = null;
topReturnButtonName = null;
currentPosition = 0;
needReload = false;
topRightButtonList = null;
}
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,357 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.util.CommonUtil;
import zuo.biao.library.util.Log;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
/**基础自定义View
* @author Lemon
* @param <T> 数据模型(model/JavaBean)
* @see OnViewClickListener
* @see #onDestroy
* @use extends BaseView<T>, 具体参考.DemoView
*/
public abstract class BaseView<T> {
private static final String TAG = "BaseView";
/**
* 传入的Activity,可在子类直接使用
*/
public Activity context;
public Resources resources;
public BaseView(Activity context, Resources resources) {
this.context = context;
this.resources = resources;
}
/**点击View的事件监听回调主要是为了activity或fragment间接通过adapter接管baseView的点击事件
* @param <T>
* @param <BV>
* @must 子类重写setOnClickListener方法且view.setOnClickListener(listener)事件统一写在这个方法里面
*/
public interface OnViewClickListener<T, BV extends BaseView<T>> {
/**onClick(v)事件由这个方法接管
* @param v
* @param bv
*/
void onViewClick(View v, BV bv);
}
/**数据改变回调接口
* (Object) getData() - 改变的数据
*/
public interface OnDataChangedListener {
void onDataChanged();
}
public OnDataChangedListener onDataChangedListener;//数据改变回调监听回调的实例
/**设置数据改变事件监听回调
* @param listener
*/
public void setOnDataChangedListener(OnDataChangedListener listener) {
onDataChangedListener = listener;
}
public OnTouchListener onTouchListener;//接触View回调监听回调的实例
/**设置接触View事件监听回调
* @param listener
*/
public void setOnTouchListener(OnTouchListener listener) {
onTouchListener = listener;
}
public OnClickListener onClickListener;//点击View回调监听回调的实例
/**设置点击View事件监听回调
* @param listener
*/
public void setOnClickListener(OnClickListener listener) {
onClickListener = listener;
if (onClickViewList != null) {
for (View v : onClickViewList) {
if (v != null) {
v.setOnClickListener(listener);
}
}
}
}
public OnLongClickListener onLongClickListener;//长按View回调监听回调的实例
/**设置长按View事件监听回调
* @param listener
*/
public void setOnLongClickListener(OnLongClickListener listener) {
onLongClickListener = listener;
}
/**
* 子类整个视图,可在子类直接使用
* @must createView方法内对其赋值且不能为null
*/
protected View convertView = null;
protected List<View> onClickViewList;
/**通过id查找并获取控件使用时不需要强转
* @param id
* @return
*/
@SuppressWarnings("unchecked")
public <V extends View> V findViewById(int id) {
return (V) convertView.findViewById(id);
}
/**通过id查找并获取控件并setOnClickListener
* @param id
* @param listener
* @return
*/
public <V extends View> V findViewById(int id, OnClickListener listener) {
V v = findViewById(id);
v.setOnClickListener(listener);
if (onClickViewList == null) {
onClickViewList = new ArrayList<View>();
}
onClickViewList.add(v);
return v;
}
/**
* 视图类型部分情况下需要根据viewType使用不同layout对应Adapter的itemViewType
*/
protected int viewType = 0;
/**
* data在列表中的位置
* @must 只使用bindView(int position, T data)方法来设置position保证position与data对应正确
*/
protected int position = 0;
/**获取data在列表中的位置
*/
public int getPosition() {
return position;
}
/**创建一个新的View
* @param inflater - @NonNull布局解释器
* @param viewType - 视图类型部分情况下需要根据viewType使用不同layout
* @return
*/
public View createView(LayoutInflater inflater, int position, int viewType) {
this.position = position;
this.viewType = viewType;
return createView(inflater);
}
/**创建一个新的View
* @param inflater - @NonNull布局解释器
* @return
*/
public abstract View createView(LayoutInflater inflater);
/**获取convertView的宽度
* @warn 只能在createView后使用
* @return
*/
public int getWidth() {
return convertView.getWidth();
}
/**获取convertView的高度
* @warn 只能在createView后使用
* @return
*/
public int getHeight() {
return convertView.getHeight();
}
protected T data = null;
/**获取数据
* @return
*/
public T getData() {
return data;
}
/**设置并显示内容建议在子类bindView内this.data = data;
* @warn 只能在createView后使用
* @param data - 传入的数据
* @param position - data在列表中的位置
* @param viewType - 视图类型部分情况下需要根据viewType使用不同layout
*/
public void bindView(T data, int position, int viewType) {
this.position = position;
this.viewType = viewType;
bindView(data);
}
/**设置并显示内容建议在子类bindView内this.data = data;
* @warn 只能在createView后使用
* @param data - 传入的数据
*/
public abstract void bindView(T data);
/**获取可见性
* @warn 只能在createView后使用
* @return 可见性 (View.VISIBLE, View.GONE, View.INVISIBLE);
*/
public int getVisibility() {
return convertView.getVisibility();
}
/**设置可见性
* @warn 只能在createView后使用
* @param visibility - 可见性 (View.VISIBLE, View.GONE, View.INVISIBLE);
*/
public void setVisibility(int visibility) {
convertView.setVisibility(visibility);
}
/**设置背景
* @warn 只能在createView后使用
* @param resId
*/
public void setBackground(int resId) {
if (resId > 0 && convertView != null) {
try {
convertView.setBackgroundResource(resId);
} catch (Exception e) {
Log.e(TAG, "setBackground try { convertView.setBackgroundResource(resId);" +
" \n >> } catch (Exception e) { \n" + e.getMessage());
}
}
}
// /**性能不好
// * @param id
// * @param s
// */
// public void setText(int id, String s) {
// TextView tv = (TextView) findViewById(id);
// tv.setText(s);
// }
//resources方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public final Resources getResources() {
if(resources == null) {
resources = context.getResources();
}
return resources;
}
public String getString(int id) {
return getResources().getString(id);
}
public int getColor(int id) {
return getResources().getColor(id);
}
public Drawable getDrawable(int id) {
return getResources().getDrawable(id);
}
public float getDimension(int id) {
return getResources().getDimension(id);
}
//resources方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//show short toast 方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param stringResId
*/
public void showShortToast(int stringResId) {
CommonUtil.showShortToast(context, stringResId);
}
/**快捷显示short toast方法需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写
* @param string
*/
public void showShortToast(String string) {
CommonUtil.showShortToast(context, string);
}
//show short toast 方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//启动新Activity方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**打开新的Activity向左滑入效果
* @param intent
*/
public void toActivity(final Intent intent) {
CommonUtil.toActivity(context, intent);
}
/**打开新的Activity
* @param intent
* @param showAnimation
*/
public void toActivity(final Intent intent, final boolean showAnimation) {
CommonUtil.toActivity(context, intent, showAnimation);
}
/**打开新的Activity向左滑入效果
* @param intent
* @param requestCode
*/
public void toActivity(final Intent intent, final int requestCode) {
CommonUtil.toActivity(context, intent, requestCode);
}
/**打开新的Activity
* @param intent
* @param requestCode
* @param showAnimation
*/
public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) {
CommonUtil.toActivity(context, intent, requestCode, showAnimation);
}
//启动新Activity方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**销毁并回收内存建议在对应的View占用大量内存时使用
* @warn 只能在UI线程中调用
*/
public void onDestroy() {
if (convertView != null) {
try {
convertView.destroyDrawingCache();
} catch (Exception e) {
Log.w(TAG, "onDestroy try { convertView.destroyDrawingCache();" +
" >> } catch (Exception e) {\n" + e.getMessage());
}
convertView = null;
}
onDataChangedListener = null;
onTouchListener = null;
onClickListener = null;
onLongClickListener = null;
onClickViewList = null;
data = null;
position = 0;
context = null;
}
}

View File

@ -1,107 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import zuo.biao.library.base.BaseView.OnViewClickListener;
import zuo.biao.library.interfaces.AdapterViewPresenter;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
/**基础Adapter使用自定义View
* <br> 适用于ListView,GridView等AbsListView的子类
* @author Lemon
* @param <T> 数据模型(model/JavaBean)
* @param <BV> BaseView的子类
* @see #setOnViewClickListener
* @use extends BaseViewAdapter<T, BV>, 具体参考 .DemoAdapter3
*/
public abstract class BaseViewAdapter<T, BV extends BaseView<T>> extends BaseAdapter<T>
implements AdapterViewPresenter<T, BV> {
// private static final String TAG = "BaseViewAdapter";
public OnViewClickListener<T, BV> onViewClickListener;
/**为ItemView设置点击View的事件监听
* @param listener
* @see BaseView.OnViewClickListener
*/
public void setOnViewClickListener(OnViewClickListener<T, BV> listener) {
onViewClickListener = listener;
}
private AdapterViewPresenter<T, BV> presenter;
/**在子类构造方法内使用可重写AdapterViewPresenter里的方法
* @param presenter
*/
protected final void setPresenter(AdapterViewPresenter<T, BV> presenter) {
this.presenter = presenter;
}
/**
* @return presenter == null ? this : presenter;
*/
protected final AdapterViewPresenter<T, BV> getPresenter() {
return presenter == null ? this : presenter;
}
public BaseViewAdapter(Activity context) {
super(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
@SuppressWarnings("unchecked")
BV bv = convertView == null ? null : (BV) convertView.getTag();
if (bv == null) {
bv = getPresenter().createView(position, parent);
convertView = bv.createView(inflater, position, getItemViewType(position));
setOnClickListener(bv);//比在bindView里调用效率高像是小众需求应该去掉直接在子类针对性地实现
convertView.setTag(bv);
}
getPresenter().bindView(position, bv);
return super.getView(position, convertView, parent);
}
/**bv的显示方法
* @param position
* @param bv
*/
@Override
public void bindView(int position, BV bv) {
bv.bindView(getItem(position), position, getItemViewType(position));
}
/**设置对ItemView点击事件的处理
* @param bv
*/
protected void setOnClickListener(final BV bv) {
if (onViewClickListener != null) {
bv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onViewClickListener.onViewClick(v, bv);
}
});
}
}
}

View File

@ -1,219 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.base;
import zuo.biao.library.R;
import zuo.biao.library.interfaces.ViewPresenter;
import zuo.biao.library.util.StringUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**基础带标签的FragmentActivity
* @author Lemon
* @see #onCreate
* @see #setContentView
* @use extends BaseViewBottomWindow, 具体参考.DemoTabActivity
* @must 在子类onCreate中调用initView();initData();initEvent();
*/
public abstract class BaseViewBottomWindow<T, BV extends BaseView<T>> extends BaseBottomWindow
implements ViewPresenter {
// private static final String TAG = "BaseViewBottomWindow";
/**
* @param savedInstanceState
* @return
* @must 1.不要在子类重复这个类中onCreate中的代码;
* 2.在子类onCreate中super.onCreate(savedInstanceState);
* initView();initData();initEvent();
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
onCreate(savedInstanceState, 0);
}
/**
* @param savedInstanceState
* @param layoutResID activity全局视图view的布局资源id <= 0 ? R.layout.base_view_bottom_window : layoutResID
* @return
* @must 1.不要在子类重复这个类中onCreate中的代码;
* 2.在子类onCreate中super.onCreate(savedInstanceState, layoutResID, listener);
* initView();initData();initEvent();
*/
protected final void onCreate(Bundle savedInstanceState, int layoutResID) {
super.onCreate(savedInstanceState);
super.setContentView(layoutResID <= 0 ? R.layout.base_view_bottom_window : layoutResID);
}
// //重写setContentView后这个方法一定会被调用final有无都会导致崩溃去掉throw Exception也会导致contentView为null而崩溃
// //防止子类中setContentView <<<<<<<<<<<<<<<<<<<<<<<<
// /**
// * @warn 不支持setContentView传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法
// */
// @Override
// public final void setContentView(int layoutResID) {
// setContentView(null);
// }
// /**
// * @warn 不支持setContentView传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法
// */
// @Override
// public final void setContentView(View view) {
// setContentView(null, null);
// }
// /**
// * @warn 不支持setContentView传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法
// */
// @Override
// public final void setContentView(View view, LayoutParams params) {
// throw new UnsupportedOperationException(TAG + "不支持setContentView" +
// "传界面布局请使用onCreate(Bundle savedInstanceState, int layoutResID)等方法");
// }
// //防止子类中setContentView >>>>>>>>>>>>>>>>>>>>>>>>>
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected ViewGroup llBaseViewBottomWindowContainer;
@Nullable
protected TextView tvBaseViewBottomWindowReturn;
@Nullable
protected TextView tvBaseViewBottomWindowForward;
/**
* 如果在子类中调用(即super.initView());则view必须含有initView中初始化用到的id(@Nullable标记)且id对应的View的类型全部相同
* 否则必须在子类initView中重写这个类中initView内的代码(所有id替换成可用id)
*/
@Override
public void initView() {// 必须调用
super.initView();
autoSetTitle();
llBaseViewBottomWindowContainer = (ViewGroup) findViewById(R.id.llBaseViewBottomWindowContainer);
tvBaseViewBottomWindowReturn = (TextView) findViewById(R.id.tvBaseViewBottomWindowReturn);
tvBaseViewBottomWindowForward = (TextView) findViewById(R.id.tvBaseViewBottomWindowForward);
}
// UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected T data;
protected BV containerView;
@Override
public void initData() {// 必须调用
super.initData();
if (tvBaseTitle != null) {
String title = getIntent().getStringExtra(INTENT_TITLE);
if (StringUtil.isNotEmpty(title, true) == false) {
title = getTitleName();
}
tvBaseTitle.setVisibility(StringUtil.isNotEmpty(title, true) ? View.VISIBLE : View.GONE);
tvBaseTitle.setText(StringUtil.getTrimedString(title));
}
if (tvBaseViewBottomWindowReturn != null && StringUtil.isNotEmpty(getReturnName(), true)) {
tvBaseViewBottomWindowReturn.setText(StringUtil.getCurrentString());
}
if (tvBaseViewBottomWindowForward != null && StringUtil.isNotEmpty(getForwardName(), true)) {
tvBaseViewBottomWindowForward.setText(StringUtil.getCurrentString());
}
llBaseViewBottomWindowContainer.removeAllViews();
if (containerView == null) {
containerView = createView();
llBaseViewBottomWindowContainer.addView(containerView.createView(inflater));
}
containerView.bindView(null);
}
/**
* 创建新的内容View
* @return
*/
protected abstract BV createView();
// Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {// 必须调用
super.initEvent();
}
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
protected void onDestroy() {
data = null;
llBaseViewBottomWindowContainer.removeAllViews();
if (containerView != null) {
containerView.onDestroy();
}
super.onDestroy();
llBaseViewBottomWindowContainer = null;
containerView = null;
}
// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,22 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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.*/
/**
* 基础类所在包
*/
/**
* @author Lemon
* @use 通用使用方法extends BaseXX
*/
package zuo.biao.library.base;

View File

@ -1,44 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
import android.app.Activity;
import android.view.View;
/**Activity的逻辑接口
* @author Lemon
* @use implements ActivityPresenter
* @warn 对象必须是Activity
*/
public interface ActivityPresenter extends Presenter {
/**获取Activity
* @must 在非抽象Activity中 return this;
*/
public Activity getActivity();//无public导致有时自动生成的getActivity方法会缺少public且对此报错
/**返回按钮被点击
* *Activity的返回按钮和底部弹窗的取消按钮几乎是必备正好原生支持反射而其它比如Fragment极少用到也不支持反射
* @param v
*/
public void onReturnClick(View v);
/**前进按钮被点击
* *Activity常用导航栏右边按钮而且底部弹窗BottomWindow的确定按钮是必备而其它比如Fragment极少用到也不支持反射
* @param v
*/
public void onForwardClick(View v);
}

View File

@ -1,39 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
import android.widget.BaseAdapter;
/**Adapter使用回调
* @author Lemon
* @param <A> adapter名称
* @see #createAdapter
* @see #refreshAdapter
* @use implements AdapterCallBack<A>,具体参考.DemoListActivity和.DemoListFragment
*/
public interface AdapterCallBack<A extends BaseAdapter> {
/**创建一个Adapter
* @return new A();
*/
A createAdapter();
/**
* BaseAdapter#notifyDataSetChanged()有时无效有时因列表更新不及时而崩溃所以需要在自定义adapter内自定义一个刷新方法
* 为什么不直接让自定义Adapter implement OnRefreshListener从而直接 onRefreshListener.onRefresh(List<T> list)
* 因为这样的话会不兼容部分 Android SDK 第三方库的Adapter
*/
void refreshAdapter();
}

View File

@ -1,21 +0,0 @@
package zuo.biao.library.interfaces;
import android.view.ViewGroup;
public interface AdapterViewPresenter<T, V> {
/**生成新的BV
* @param position
* @param parent
* @return
*/
public abstract V createView(int position, ViewGroup parent);
/**设置BV显示
* @param position
* @param bv
* @return
*/
public abstract void bindView(int position, V bv);
}

View File

@ -1,49 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**缓存回调
* @author Lemon
* @param <T>
* @use .DemoListActivity .UserListFragment
*/
public interface CacheCallBack<T> {
/**
* 获取缓存的类通常是数据模型(model/JavaBean)
* @warn Entry<K, V>这种带类型(这里是K和V)的类不能作为返回值应该用其它不带类型的类(比如.User)替换
* @return null-不缓存
*/
Class<T> getCacheClass();
/**
* 获取缓存的分组
* @return 含非空字符的String 缓存至对应class的group中 : 至缓存至对应class中
*/
String getCacheGroup();
/**
* 获取缓存单个数据的id
* @param data
* @return data == null ? null : "" + data.getId(); //不用long是因为某些数据(例如订单)的id超出long的最大值
*/
String getCacheId(T data);
/**
* 获取缓存每页数量
* @return > 0 缓存 : 不缓存
*/
int getCacheCount();
}

View File

@ -1,35 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
import android.app.Activity;
/**Fragment的逻辑接口
* @author Lemon
* @use implements FragmentPresenter
* @warn 对象必须是Fragment
*/
public interface FragmentPresenter extends Presenter {
/**
* 该Fragment在Activity添加的所有Fragment中的位置
*/
static final String ARGUMENT_POSITION = "ARGUMENT_POSITION";
static final String ARGUMENT_ID = "ARGUMENT_ID";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";
static final int RESULT_OK = Activity.RESULT_OK;
static final int RESULT_CANCELED = Activity.RESULT_CANCELED;
}

View File

@ -1,24 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**添加回调
* @author Lemon
* @param <T>
*/
public interface OnAddListener<T> {
void onAdd(T object);
}

View File

@ -1,27 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**拖拽View底部的回调接口
* @author Lemon
* @use implements OnBottomDragListener
*/
public interface OnBottomDragListener {
/**
* @param rightToLeft 从右向左 : 从左向右
*/
void onDragBottom(boolean rightToLeft);
}

View File

@ -1,24 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**进度回调
* @author Lemon
* @param <T>
*/
public interface OnProgressListener {
void onProgressUpdate(int progress);
}

View File

@ -1,35 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
import android.view.View;
/**到达接触到View的某个边界的监听回调
* 一般用于一个ViewGroupparent内的Viewchild接触到parent的事件监听
* @author Lemon
* @use implements OnReachViewBorderListener
*/
public interface OnReachViewBorderListener {
static final int TYPE_TOP = 0;
static final int TYPE_BOTTOM = 1;
static final int TYPE_LEFT = 2;
static final int TYPE_RIGHT = 3;
/**到达接触到v的某个边界type
* @param type 边界类型
* @param v 目标View一般为ViewGroupListViewGridView等
*/
void onReach(int type, View v);
}

View File

@ -1,24 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**移除回调
* @author Lemon
* @param <T>
*/
public interface OnRemoveListener<T> {
void onRemove(T object);
}

View File

@ -1,24 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**结果回调
* @author Lemon
* @param <T>
*/
public interface OnResultListener<T> {
void onResult(T result);
}

View File

@ -1,31 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**停止加载监听回调
* @author Lemon
* @use implements OnStopLoadListener
*/
public interface OnStopLoadListener {
/**
* 停止刷新
*/
void onStopRefresh();
/**
* 停止加载更多
* @param isHaveMore 还有未加载的数据
*/
void onStopLoadMore(boolean isHaveMore);
}

View File

@ -1,65 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
/**Activity和Fragment的公共逻辑接口
* @author Lemon
* @use Activity或Fragment implements Presenter
*/
public interface Presenter {
static final String INTENT_TITLE = "INTENT_TITLE";
static final String INTENT_ID = "INTENT_ID";
static final String INTENT_TYPE = "INTENT_TYPE";
static final String INTENT_PHONE = "INTENT_PHONE";
static final String INTENT_PASSWORD = "INTENT_PASSWORD";
static final String INTENT_VERIFY = "INTENT_VERIFY";
static final String INTENT_USER_ID = "INTENT_USER_ID";
static final String RESULT_DATA = "RESULT_DATA";
static final String RESULT_ID = "RESULT_ID";
static final String RESULT_TYPE = "RESULT_TYPE";
static final String RESULT_PHONE = "RESULT_PHONE";
static final String RESULT_PASSWORD = "RESULT_PASSWORD";
static final String RESULT_VERIFY = "RESULT_VERIFY";
static final String RESULT_USER_ID = "RESULT_USER_ID";
static final String ACTION_EXIT_APP = "ACTION_EXIT_APP";
/**
* UI显示方法(操作UI但不存在数据获取或处理代码也不存在事件监听代码)
* @must Activity-在子类onCreate方法内初始化View(setContentView)后调用Fragment-在子类onCreateView方法内初始化View后调用
*/
void initView();
/**
* Data数据方法(存在数据获取或处理代码但不存在事件监听代码)
* @must Activity-在子类onCreate方法内初始化View(setContentView)后调用Fragment-在子类onCreateView方法内初始化View后调用
*/
void initData();
/**
* Event事件方法(只要存在事件监听代码就是)
* @must Activity-在子类onCreate方法内初始化View(setContentView)后调用Fragment-在子类onCreateView方法内初始化View后调用
*/
void initEvent();
/**
* 是否存活(已启动且未被销毁)
*/
boolean isAlive();
/**
* 是否在运行
*/
boolean isRunning();
}

View File

@ -1,43 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.interfaces;
import android.support.annotation.Nullable;
/**View的逻辑接口
* @author Lemon
* @use implements ViewPresenter
*/
public interface ViewPresenter {
/**获取导航栏标题名
* @return null - View.GONE; "" - View.GONE; "xxx" - "xxx"
*/
@Nullable
public String getTitleName();
/**获取导航栏返回按钮名
* @return null - default; "" - default; "xxx" - "xxx"
*/
@Nullable
public String getReturnName();
/**获取导航栏前进按钮名
* @return null - default; "" - default; "xxx" - "xxx"
*/
@Nullable
public String getForwardName();
}

View File

@ -1,22 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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.*/
/**
* 回调接口类所在包
*/
/**
* @author Lemon
* @use 通用使用方法implements XXInterface
*/
package zuo.biao.library.interfaces;

View File

@ -1,205 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.manager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import zuo.biao.library.util.JSON;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.StringUtil;
import android.content.Context;
import android.content.SharedPreferences;
/**磁盘缓存类
* @author Lemon
* @param <T> 缓存的数据类
* @use new Cache<T>(context, clazz, path).xxxMethod(...);具体参考.CacheManager
*/
public class Cache<T> {
public static final String TAG = "Cache";
public Cache(Context context, Class<T> clazz, String path) {
this(context, clazz, context.getSharedPreferences(StringUtil.getTrimedString(path), Context.MODE_PRIVATE));
}
@SuppressWarnings("unused")
private Context context;
private Class<T> clazz;
private SharedPreferences sp;
public Cache(Context context, Class<T> clazz, SharedPreferences sp) {
this.context = context;
this.clazz = clazz;
this.sp = sp;
}
/**获取列表大小
* @return
*/
public int getSize() {
Map<String, ?> map = sp.getAll();
return map == null ? 0 : map.size();
}
/**保存
* @param map
*/
public void saveList(Map<String, T> map) {
if (map == null) {
Log.e(TAG, "saveList map == null >> return;");
return;
}
Set<String> keySet = map.keySet();
if (keySet != null) {
for (String id: keySet) {
save(id, map.get(id));
}
}
}
/**保存
* @param key
* @param value
*/
public void save(String key, T value) {
if (StringUtil.isNotEmpty(key, true) == false || value == null) {
Log.e(TAG, "save StringUtil.isNotEmpty(key, true) == false || value == null >> return;");
return;
}
key = StringUtil.getTrimedString(key);
sp.edit().remove(key).putString(key, JSON.toJSONString(value)).commit();
}
/**判断是否已存
* @param key
* @return
*/
public boolean isContain(String key) {
if (StringUtil.isNotEmpty(key, true) == false) {
Log.e(TAG, "isContain StringUtil.isNotEmpty(key, true) == false >> return false;");
return false;
}
return sp.contains(StringUtil.getTrimedString(key));
}
/**获取
* @param key
* @return
*/
public T get(String key) {
if (StringUtil.isNotEmpty(key, true) == false) {
Log.e(TAG, "get (sp == null" +
" || StringUtil.isNotEmpty(key, true) == false >> return null; ");
return null;
}
return JSON.parseObject(sp.getString(StringUtil.getTrimedString(key), null), clazz);
}
/**ROOT
* 获取列表
* @return
*/
@SuppressWarnings("unchecked")
public Map<String, String> getMap() {
try {
return (Map<String, String>) sp.getAll();
} catch (Exception e) {
Log.e(TAG, "getMap try { return (Map<String, String>) sp.getAll();" +
"}catch(Exception e) {\n " + e.getMessage());
}
return null;
}
/**ROOT
* 获取列表
* @return
*/
public Set<String> getKeySet() {
Map<String, String> map = getMap();
return map == null ? null : map.keySet();
}
/**ROOT
* 获取列表
* @param start < 0 ? all : [start, end]
* @param end
* @return
*/
public List<T> getValueList(int start, int end) {
List<T> list = getAllValueList();
return start < 0 || start > end || list == null || end >= list.size() ? list : list.subList(start, end);
}
/**ROOT
* 获取列表,顺序由keyList指定
* @param keyList
* @return
*/
public List<T> getValueList(List<String> keyList) {
if (keyList != null) {
List<T> list = new ArrayList<T>();
T data;
for (String key : keyList) {
data = get(key);
if (data != null) {
list.add(data);
}
}
return list;
}
return null;
}
/**ROOT
* 获取列表
* @return
*/
public List<T> getAllValueList() {
Map<String, String> map = getMap();
if (map != null) {
List<T> list = new ArrayList<T>();
T data;
for (String value : map.values()) {
data = JSON.parseObject(value, clazz);
if (data != null) {
list.add(data);
}
}
return list;
}
return null;
}
/**删除
* @param key
*/
public void remove(String key) {
if (StringUtil.isNotEmpty(key, true) == false) {
Log.e(TAG, "deleteGroup context == null " +
" || StringUtil.isNotEmpty(groupName, true) == fal >> return;");
return;
}
sp.edit().remove(StringUtil.getTrimedString(key)).commit();
}
}

View File

@ -1,412 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.manager;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import zuo.biao.library.base.BaseApplication;
import zuo.biao.library.util.DataKeeper;
import zuo.biao.library.util.JSON;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.StringUtil;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
/**磁盘缓存管理类
* @author Lemon
* @use CacheManager.getInstance().xxxMethod(...);具体参考.BaseListActivity
*/
public class CacheManager {
private static final String TAG = "CacheManager";
public static final String CACHE_PATH = DataKeeper.ROOT_SHARE_PREFS_ + "CACHE_PATH";
private Context context;
private CacheManager(Context context) {
this.context = context;
}
private static CacheManager manager;
public static synchronized CacheManager getInstance() {
if (manager == null) {
manager = new CacheManager(BaseApplication.getInstance());
}
synchronized (CacheManager.class) {
if (manager == null) {
manager = new CacheManager(BaseApplication.getInstance());
}
return manager;
}
}
/**
* @param clazz
* @return
*/
public <T> String getClassPath(Class<T> clazz) {
return clazz == null ? null : CACHE_PATH + clazz.getName();
}
/**
* @param clazz
* @return
*/
public <T> String getListPath(Class<T> clazz) {
String classPath = getClassPath(clazz);
return StringUtil.isNotEmpty(classPath, true) ? classPath + KEY_LIST : null;
}
/**
* @param clazz
* @param group
* @return
*/
public <T> String getGroupPath(Class<T> clazz) {
String classPath = getClassPath(clazz);
return StringUtil.isNotEmpty(classPath, true) == false ? null : classPath + KEY_GROUP;
}
private SharedPreferences getSharedPreferences(String path) {
return StringUtil.isNotEmpty(path, true) == false
? null : context.getSharedPreferences(StringUtil.getTrimedString(path), Context.MODE_PRIVATE);
}
/**
* 数据列表
*/
public static final String KEY_LIST = "LIST";
/**
* 数据分组,自定义
*/
public static final String KEY_GROUP = "GROUP";
/**
* 分组中列表每页最大数量
*/
public static final int MAX_PAGE_SIZE = 10;
/**获取列表
* @param clazz
* @return
*/
public <T> List<T> getAllList(Class<T> clazz) {
return getList(clazz, -1, 0);
}
/**获取列表
* @param clazz
* @param start
* @return
*/
public <T> List<T> getList(Class<T> clazz, int start, int pageSize) {
return getList(clazz, null, start, pageSize);
}
/**获取列表
* @param clazz
* @param group
* @return
*/
public <T> List<T> getAllList(Class<T> clazz, String group) {
return StringUtil.isNotEmpty(group, true) ? getList(clazz, group, -1, 0) : null;
}
/**获取列表
* @param clazz
* @param group == null ? all : in group
* @param start < 0 ? all in group : subList(start, end)
* @param count > 0 ? all in group : subList(start, end)
* @return
*/
public <T> List<T> getList(Class<T> clazz, String group, int start, int count) {
Log.i(TAG, "\n\n<<<<<<<<<<<<<<<<\ngetList group = " + group +"; start = " + start + "; count = " + count);
if (count <= 0 || clazz == null) {
Log.e(TAG, "getList count <= 0 || clazz == null >> return null;");
return null;
}
Cache<T> cacheList = new Cache<T>(context, clazz, getClassPath(clazz) + KEY_LIST);
if (StringUtil.isNotEmpty(group, true) == false) {
return cacheList == null ? null : cacheList.getValueList(start, start + count);
}
List<String> idList = getIdList(clazz, group);
final int totalCount = idList == null ? 0 : idList.size();
Log.i(TAG, "getList idList.size() = " + totalCount);
if (totalCount <= 0) {
Log.e(TAG, "getList totalCount <= 0 >> return null;");
return null;
}
if (start >= 0) {
Log.i(TAG, "getList start >= 0 >> ");
int end = start + count;
if (end > totalCount) {
end = totalCount;
}
Log.i(TAG, "getList end = " + end);
if (end <= start) {
Log.e(TAG, "getList end <= start >> return null;");
return null;
}
if (start > 0 || end < totalCount) {
Log.i(TAG, "getList start > 0 || end < totalCount >> idList = idList.subList(" + start + "," + end + "); >>");
idList = idList.subList(start, end);
}
}
List<T> list = new ArrayList<T>();
T data;
for (String id : idList) {
data = cacheList.get(id);
if (data != null) {
list.add(data);
}
}
Log.i(TAG, "getList return list; list.size() = " + list.size() + "\n>>>>>>>>>>>>>>>>>>>>>>\n\n");
return list;
}
/**获取单个值
* @param clazz
* @param id
* @return
*/
public <T> T get(Class<T> clazz, String id) {
Cache<T> cacheList = clazz == null
? null : new Cache<T>(context, clazz, getClassPath(clazz) + KEY_LIST);
return cacheList == null ? null : cacheList.get(id);
}
/**获取id列表
* @param clazz
* @param group
* @return
*/
public <T> List<String> getIdList(Class<T> clazz, String group) {
SharedPreferences sp = getSharedPreferences(
getClassPath(clazz) + KEY_GROUP);
return sp == null ? null : JSON.parseArray(sp.getString(StringUtil.getTrimedString(group), null), String.class);
}
/**保存列表
* @param clazz
* @param map 数据表
*/
public <T> void addList(Class<T> clazz, LinkedHashMap<String, T> map) {
saveList(clazz, null, map, 0, 0);
}
/**添加列表
* @param clazz
* @param group 分组
* @param map 数据表
*/
public <T> void addList(Class<T> clazz, String group, LinkedHashMap<String, T> map) {
addList(clazz, group, map, -1);
}
/**添加列表
* @param clazz
* @param group 分组
* @param map 数据表
* @param pageSize 每页大小
*/
public <T> void addList(Class<T> clazz, String group, LinkedHashMap<String, T> map, int pageSize) {
if (StringUtil.isNotEmpty(group, true) == false) {
Log.e(TAG, "addList StringUtil.isNotEmpty(group, true) == false >> return;");
return;
}
saveList(clazz, group, map, -1, pageSize);
}
/**保存列表
* @param clazz
* @param group 分组
* @param map 数据表
* @param start 存储起始位置,[start, start + map.size()]中原有的将被替换. start = start < 0 ? idList.size() : start;
* @param pageSize 每页大小
*/
public <T> void saveList(Class<T> clazz, String group, LinkedHashMap<String, T> map, int start, int pageSize) {
Log.i(TAG, "\n\n <<<<<<<<<<<<<<<<<\nsaveList group = " + group + "; start = " + start + "; pageSize = " + pageSize);
if (clazz == null || map == null || map.size() <= 0) {
Log.e(TAG, "saveList clazz == null || map == null || map.size() <= 0 >> return;");
return;
}
final String CLASS_PATH = getClassPath(clazz);
if (StringUtil.isNotEmpty(group, true)) {
group = StringUtil.getTrimedString(group);
Log.i(TAG, "saveList group = " + group + "; map.size() = " + map.size()
+ "; start = " + start +"; pageSize = " + pageSize);
List<String> newIdList = new ArrayList<String>(map.keySet());//用String而不是Long因为订单Order的id超出Long的最大值
Log.i(TAG, "saveList newIdList.size() = " + newIdList.size() + "; start save <<<<<<<<<<<<<<<<<\n ");
//保存至分组<<<<<<<<<<<<<<<<<<<<<<<<<
SharedPreferences sp = getSharedPreferences(CLASS_PATH + KEY_GROUP);
// sp.edit().putString(KEY_GROUP, group);
Editor editor = sp.edit();
Log.i(TAG, "\n saveList pageSize = " + pageSize + " <<<<<<<<");
//列表每页大小
if (pageSize > 0) {
if (pageSize > MAX_PAGE_SIZE) {
pageSize = MAX_PAGE_SIZE;
}
}
Log.i(TAG, "\n saveList pageSize = " + pageSize + ">>>>>>>>>");
//id列表
List<String> idList = JSON.parseArray(sp.getString(group, null), String.class);
if (idList == null) {
idList = new ArrayList<String>();
}
if (start < 0) {
start = idList.size();
}
Log.i(TAG, "\n saveList idList.size() = " + idList.size() + " <<<<<<<<");
String id;
for (int i = start; i < start + newIdList.size(); i++) {
id = newIdList.get(i - start);
if (id == null || id.isEmpty()) {
continue;
}
if (idList.contains(id)) {
idList.remove(id);//位置发生变化
}
if (i < idList.size()) {
idList.set(i, id);
} else {
idList.add(id);
}
}
editor.remove(group).putString(group, JSON.toJSONString(idList)).commit();
Log.i(TAG, "\n saveList idList.size() = " + idList.size() + " >>>>>>>>");
}
//保存至分组>>>>>>>>>>>>>>>>>>>>>>>>>
//保存所有数据<<<<<<<<<<<<<<<<<<<<<<<<<
Cache<T> cache = new Cache<T>(context, clazz, CLASS_PATH + KEY_LIST);
cache.saveList(map);
//保存所有数据>>>>>>>>>>>>>>>>>>>>>>>>>
Log.i(TAG, "saveList cache.getSize() = " + cache.getSize() + "; end save \n>>>>>>>>>>>>>>>>>> \n\n");
// }
}
/**保存
* 未完成
* @param clazz
* @param data 数据
* @param id
*/
public <T> void save(Class<T> clazz, T data, String id) {
save(clazz, data, id, null);
}
/**ROOT
* 保存
* @param clazz
* @param data 数据
* @param id
* @param group 分组
*/
public <T> void save(Class<T> clazz, T data, String id, String group) {
if (data == null || StringUtil.isNotEmpty(id, true) == false) {
Log.e(id, "save data == null || StringUtil.isNotEmpty(id, true) == false >> return;");
return;
}
new Cache<T>(context, clazz, getListPath(clazz)).save(id, data);
SharedPreferences sp = getSharedPreferences(getGroupPath(clazz));
if (sp != null) {
group = StringUtil.getTrimedString(group);
Log.i(TAG, "save sp != null >> save to group");
List<String> idList = getIdList(clazz, group);
if (idList == null) {
idList = new ArrayList<String>();
}
if (idList.contains(id) == false) {
Log.i(TAG, "save idList.contains(id) == false >> add");
idList.add(0, id);
sp.edit().remove(group).putString(group, JSON.toJSONString(idList)).commit();
}
}
}
/**清空类
* @param <T>
* @param clazz
*/
public <T> void clear(Class<T> clazz) {
clear(getSharedPreferences(getListPath(clazz)));
}
/**清空群组
* @param <T>
* @param clazz
* @param group
*/
public <T> void clear(Class<T> clazz, String group) {
clear(clazz, group, false);
}
/**清空群组
* @param clazz
* @param group
* @param removeAllInGroup 删除群组内所有id对应数据
* @param <T>
*/
public <T> void clear(Class<T> clazz, String group, boolean removeAllInGroup) {
Log.i(TAG, "clear group = " + group + "; removeAllInGroup = " + removeAllInGroup);
List<String> list = removeAllInGroup == false ? null : getIdList(clazz, group);
if (list != null) {
Cache<T> cache = new Cache<T>(context, clazz, getListPath(clazz));
for (String id : list) {
cache.remove(id);
}
}
clear(getSharedPreferences(getGroupPath(clazz)));
}
/**清空
* @param sp
*/
public void clear(SharedPreferences sp) {
if (sp == null) {
Log.e(TAG, "clearList sp == null >> return;");
return;
}
sp.edit().clear().commit();
}
public <T> void remove(Class<T> clazz, String id) {
if (clazz == null) {
Log.e(TAG, "remove clazz == null >> return;");
return;
}
new Cache<T>(context, clazz, getListPath(clazz)).remove(id);
}
}

View File

@ -1,207 +0,0 @@
package zuo.biao.library.manager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.model.City;
import zuo.biao.library.util.StringUtil;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.text.TextUtils;
/**地区管理类
* @author Lemon
* @use CityDB.getInstance(...).xxMethod(...)
*/
public class CityDB {
public static final String CITY_DB_NAME = "city.db";
private static final String CITY_TABLE_NAME = "city";
private SQLiteDatabase db;
public CityDB(Context context, String path) {
db = context.openOrCreateDatabase(path, Context.MODE_PRIVATE, null);
}
private static CityDB cityDB;
public static synchronized CityDB getInstance(Context context, String packageName) {
if (cityDB == null) {
cityDB = openCityDB(context, packageName);
}
return cityDB;
}
private static CityDB openCityDB(Context context, String packageName) {
String path = "/data"
+ Environment.getDataDirectory().getAbsolutePath()
+ File.separator + packageName + File.separator
+ CityDB.CITY_DB_NAME;
File db = new File(path);
if (!db.exists()) {
try {
InputStream is = context.getAssets().open("city.db");
FileOutputStream fos = new FileOutputStream(db);
int len = -1;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
fos.flush();
}
fos.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
return new CityDB(context, path);
}
public List<City> getAllCity() {
List<City> list = new ArrayList<City>();
Cursor c = db.rawQuery("SELECT * from " + CITY_TABLE_NAME, null);
while (c.moveToNext()) {
String province = c.getString(c.getColumnIndex("province"));
String city = c.getString(c.getColumnIndex("city"));
Double latitude = c.getDouble(c.getColumnIndex("latitude"));
Double longitude = c.getDouble(c.getColumnIndex("longitude"));
City item = new City(province, city, latitude, longitude);
list.add(item);
}
return list;
}
public List<String> getAllProvince() {
List<String> list = new ArrayList<String>();
Cursor c = db.rawQuery("SELECT distinct province from " + CITY_TABLE_NAME, null);
while (c.moveToNext()) {
String province = c.getString(c.getColumnIndex("province"));
list.add(province);
}
return list;
}
/**
* 拿到省的所有 地级市
*
* @return
*/
public List<String> getProvinceAllCity(String province) {
province = StringUtil.getTrimedString(province);
if (province.length() <= 0) {
return null;
}
List<String> list = new ArrayList<String>();
Cursor c = db.rawQuery("SELECT distinct city from " + CITY_TABLE_NAME + " where province = ? ", new String[]{province});
while (c.moveToNext()) {
String city = c.getString(c.getColumnIndex("city"));
list.add(city);
}
return list;
}
/**
* 拿到所有的 县或区
*
* @return
*/
public List<String> getAllCountry(String province, String city) {
province = StringUtil.getTrimedString(province);
if (province.length() <= 0) {
return null;
}
city = StringUtil.getTrimedString(city);
if (city.length() <= 0) {
return null;
}
List<String> list = new ArrayList<String>();
Cursor c = db.rawQuery("SELECT country from " + CITY_TABLE_NAME + " where province = ? and city = ?", new String[]{province, city});
while (c.moveToNext()) {
String country = c.getString(c.getColumnIndex("country"));
list.add(country);
}
return list;
}
public City getCity(String city) {
if (TextUtils.isEmpty(city))
return null;
City item = getCityInfo(parseName(city));
if (item == null) {
item = getCityInfo(city);
}
return item;
}
/**
* 去掉市或县搜索
*
* @param city
* @return
*/
private String parseName(String city) {
if (city.contains("")) {// 如果为空就去掉市字再试试
String subStr[] = city.split("");
city = subStr[0];
} else if (city.contains("")) {// 或者去掉县字再试试
String subStr[] = city.split("");
city = subStr[0];
}
return city;
}
private City getCityInfo(String city) {
Cursor c = db.rawQuery("SELECT * from " + CITY_TABLE_NAME
+ " where city=?", new String[]{city});
if (c.moveToFirst()) {
String province = c.getString(c.getColumnIndex("province"));
String name = c.getString(c.getColumnIndex("city"));
Double latitude = c.getDouble(c.getColumnIndex("latitude"));
Double longitude = c.getDouble(c.getColumnIndex("longitude"));
City item = new City(province, name, latitude, longitude);
return item;
}
return null;
}
/**
* 查询附近的城市
* 画正方形
*/
public List<String> getNearbyCityList(String sCity) {
City city = getCity(sCity);
List<String> nearbyCitysList = new ArrayList<String>();
//根据常跑地信息画正方形地域
double lat = city.getLatitude() + 0.9;
double lon = city.getLongitude() + 0.9;
double lat1 = city.getLatitude() - 0.9;
double lon1 = city.getLongitude() - 0.9;
Cursor c = db.rawQuery("SELECT * from " + CITY_TABLE_NAME + " WHERE LATITUDE < " + lat + " AND LATITUDE > " + lat1 +
" AND LONGITUDE <" + lon + " AND LONGITUDE > " + lon1, null);
while (c.moveToNext()) {
String nearbyCity = c.getString(c.getColumnIndex("city"));
nearbyCitysList.add(nearbyCity);
}
return nearbyCitysList;
}
}

View File

@ -1,359 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.manager;
import java.io.IOException;
import java.net.CookieHandler;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLSocketFactory;
import org.json.JSONException;
import org.json.JSONObject;
import zuo.biao.library.base.BaseApplication;
import zuo.biao.library.model.Parameter;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.SSLUtil;
import zuo.biao.library.util.StringUtil;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
/**HTTP请求管理类
* @author Lemon
* @use HttpManager.getInstance().get(...)或HttpManager.getInstance().post(...) > 在回调方法onHttpRequestSuccess和onHttpRequestError处理HTTP请求结果
* @must 解决getTokengetResponseCodegetResponseData中的TODO
*/
public class HttpManager {
private static final String TAG = "HttpManager";
/**网络请求回调接口
*/
public interface OnHttpResponseListener {
/**
* @param requestCode 请求码自定义在发起请求的类中可以用requestCode来区分各个请求
* @param resultJson 服务器返回的Json串
* @param e 异常
*/
void onHttpResponse(int requestCode, String resultJson, Exception e);
}
private Context context;
private static HttpManager instance;// 单例
private static SSLSocketFactory socketFactory;// 单例
private HttpManager(Context context) {
this.context = context;
try {
//TODO 初始化自签名demo.cer这里demo.cer是空文件为服务器生成的自签名证书存放于assets目录下如果不需要自签名可删除
socketFactory = SSLUtil.getSSLSocketFactory(context.getAssets().open("demo.cer"));
} catch (Exception e) {
Log.e(TAG, "HttpManager try {" +
" socketFactory = SSLUtil.getSSLSocketFactory(context.getAssets().open(\"demo.cer\"));\n" +
"\t\t} catch (Exception e) {\n" + e.getMessage());
}
}
public synchronized static HttpManager getInstance() {
if (instance == null) {
instance = new HttpManager(BaseApplication.getInstance());
}
return instance;
}
/**
* 列表首页页码有些服务器设置为1即列表页码从1开始
*/
public static final int PAGE_NUM_0 = 0;
public static final String KEY_TOKEN = "token";
public static final String KEY_COOKIE = "cookie";
/**GET请求
* @param paramList 请求参数列表可以一个键对应多个值
* @param url 接口url
* @param requestCode
* 请求码类似onActivityResult中请求码当同一activity中以实现接口方式发起多个网络请求时请求结束后都会回调
* {@link OnHttpResponseListener#onHttpResponse(int, String, Exception)}<br>
* 在发起请求的类中可以用requestCode来区分各个请求
* @param listener
*/
public void get(final List<Parameter> paramList, final String url,
final int requestCode, final OnHttpResponseListener listener) {
new AsyncTask<Void, Void, Exception>() {
String result;
@Override
protected Exception doInBackground(Void... params) {
OkHttpClient client = getHttpClient(url);
if (client == null) {
return new Exception(TAG + ".get AsyncTask.doInBackground client == null >> return;");
}
StringBuffer sb = new StringBuffer();
sb.append(StringUtil.getNoBlankString(url));
if (paramList != null) {
Parameter parameter;
for (int i = 0; i < paramList.size(); i++) {
parameter = paramList.get(i);
sb.append(i <= 0 ? "?" : "&");
sb.append(StringUtil.getTrimedString(parameter.key));
sb.append("=");
sb.append(StringUtil.getTrimedString(parameter.value));
}
}
try {
result = getResponseJson(client, new Request.Builder()
.addHeader(KEY_TOKEN, getToken(url))
.url(sb.toString()).build());
//TODO 注释或删除以下 测试HttpRequest.getUser接口的数据
result = "{\"code\":100,\"data\":{\"id\":1,\"name\":\"TestName\",\"phone\":\"1234567890\"}}";
} catch (Exception e) {
Log.e(TAG, "get AsyncTask.doInBackground try { result = getResponseJson(..." +
"} catch (Exception e) {\n" + e.getMessage());
return e;
}
return null;
}
@Override
protected void onPostExecute(Exception exception) {
super.onPostExecute(exception);
listener.onHttpResponse(requestCode, result, exception);
}
}.execute();
}
/**POST请求
* @param paramList 请求参数列表可以一个键对应多个值
* @param url 接口url
* @param requestCode
* 请求码类似onActivityResult中请求码当同一activity中以实现接口方式发起多个网络请求时请求结束后都会回调
* {@link OnHttpResponseListener#onHttpResponse(int, String, Exception)}<br>
* 在发起请求的类中可以用requestCode来区分各个请求
* @param listener
*/
public void post(final List<Parameter> paramList, final String url,
final int requestCode, final OnHttpResponseListener listener) {
new AsyncTask<Void, Void, Exception>() {
String result;
@Override
protected Exception doInBackground(Void... params) {
OkHttpClient client = getHttpClient(url);
if (client == null) {
return new Exception(TAG + ".post AsyncTask.doInBackground client == null >> return;");
}
FormEncodingBuilder fBuilder = new FormEncodingBuilder();
if (paramList != null) {
for (Parameter p : paramList) {
fBuilder.add(StringUtil.getTrimedString(p.key), StringUtil.getTrimedString(p.value));
}
}
try {
result = getResponseJson(client, new Request.Builder()
.addHeader(KEY_TOKEN, getToken(url)).url(StringUtil.getNoBlankString(url))
.post(fBuilder.build()).build());
//TODO 注释或删除以下 测试HttpRequest.register接口的数据
result = "{\"code\":102}";
} catch (Exception e) {
Log.e(TAG, "post AsyncTask.doInBackground try { result = getResponseJson(..." +
"} catch (Exception e) {\n" + e.getMessage());
return e;
}
return null;
}
@Override
protected void onPostExecute(Exception exception) {
super.onPostExecute(exception);
listener.onHttpResponse(requestCode, result, exception);
}
}.execute();
}
//httpGet/httpPost 内调用方法 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**
* @param url
* @return
*/
private OkHttpClient getHttpClient(String url) {
Log.i(TAG, "getHttpClient url = " + url);
if (StringUtil.isNotEmpty(url, true) == false) {
Log.e(TAG, "getHttpClient StringUtil.isNotEmpty(url, true) == false >> return null;");
return null;
}
OkHttpClient client = new OkHttpClient();
client.setCookieHandler(new HttpHead());
client.setConnectTimeout(15, TimeUnit.SECONDS);
client.setWriteTimeout(10, TimeUnit.SECONDS);
client.setReadTimeout(10, TimeUnit.SECONDS);
//添加信任https证书,用于自签名,不需要可删除
if (url.startsWith(StringUtil.URL_PREFIXs) && socketFactory != null) {
client.setSslSocketFactory(socketFactory);
}
return client;
}
/**
* @param paramList
* @return
*/
public String getToken(String tag) {
return context.getSharedPreferences(KEY_TOKEN, Context.MODE_PRIVATE).getString(KEY_TOKEN + tag, "");
}
/**
* @param tag
* @param value
*/
public void saveToken(String tag, String value) {
context.getSharedPreferences(KEY_TOKEN, Context.MODE_PRIVATE)
.edit()
.remove(KEY_TOKEN + tag)
.putString(KEY_TOKEN + tag, value)
.commit();
}
/**
* @return
*/
public String getCookie() {
return context.getSharedPreferences(KEY_COOKIE, Context.MODE_PRIVATE).getString(KEY_COOKIE, "");
}
/**
* @param value
*/
public void saveCookie(String value) {
context.getSharedPreferences(KEY_COOKIE, Context.MODE_PRIVATE)
.edit()
.remove(KEY_COOKIE)
.putString(KEY_COOKIE, value)
.commit();
}
/**
* @param client
* @param request
* @return
* @throws Exception
*/
private String getResponseJson(OkHttpClient client, Request request) throws Exception {
if (client == null || request == null) {
Log.e(TAG, "getResponseJson client == null || request == null >> return null;");
return null;
}
Response response = client.newCall(request).execute();
return response.isSuccessful() ? response.body().string() : null;
}
/**从object中获取key对应的值
* *获取如果T是基本类型容易崩溃所以需要try-catch
* @param json
* @param key
* @return
* @throws JSONException
*/
public <T> T getValue(String json, String key) throws JSONException {
return getValue(new JSONObject(json), key);
}
/**从object中获取key对应的值
* *获取如果T是基本类型容易崩溃所以需要try-catch
* @param object
* @param key
* @return
* @throws JSONException
*/
@SuppressWarnings("unchecked")
public <T> T getValue(JSONObject object, String key) throws JSONException {
return (T) object.get(key);
}
//httpGet/httpPost 内调用方法 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**http请求头
*/
public class HttpHead extends CookieHandler {
public HttpHead() {
}
@Override
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException {
String cookie = getCookie();
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.putAll(requestHeaders);
if (!TextUtils.isEmpty(cookie)) {
List<String> cList = new ArrayList<String>();
cList.add(cookie);
map.put("Cookie", cList);
}
return map;
}
@Override
public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException {
List<String> list = responseHeaders.get("Set-Cookie");
if (list != null) {
for (int i = 0; i < list.size(); i++) {
String cookie = list.get(i);
if (cookie.startsWith("JSESSIONID")) {
saveCookie(list.get(i));
break;
}
}
}
}
}
}

View File

@ -1,566 +0,0 @@
/*
* Copyright (C) 2013 readyState Software Ltd
*
* 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 zuo.biao.library.manager;
import java.lang.reflect.Method;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout.LayoutParams;
/**系统栏背景管理器
* Class to manage status and navigation bar tint effects when using KitKat
* translucent system UI modes.
*/
public class SystemBarTintManager {
static {
// Android allows a system property to override the presence of the navigation bar.
// Used by the emulator.
// See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
@SuppressWarnings("rawtypes")
Class c = Class.forName("android.os.SystemProperties");
@SuppressWarnings("unchecked")
Method m = c.getDeclaredMethod("get", String.class);
m.setAccessible(true);
sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
} catch (Throwable e) {
sNavBarOverride = null;
}
}
}
/**
* The default system bar tint color value.
*/
public static final int DEFAULT_TINT_COLOR = 0x99000000;
private static String sNavBarOverride;
private final SystemBarConfig mConfig;
private boolean mStatusBarAvailable;
private boolean mNavBarAvailable;
private boolean mStatusBarTintEnabled;
private boolean mNavBarTintEnabled;
private View mStatusBarTintView;
private View mNavBarTintView;
/**
* Constructor. Call this in the host activity onCreate method after its
* content view has been set. You should always create new instances when
* the host activity is recreated.
*
* @param activity The host activity.
*/
@TargetApi(19)
public SystemBarTintManager(Activity activity) {
Window win = activity.getWindow();
ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// check theme attrs
int[] attrs = {android.R.attr.windowTranslucentStatus,
android.R.attr.windowTranslucentNavigation};
TypedArray a = activity.obtainStyledAttributes(attrs);
try {
mStatusBarAvailable = a.getBoolean(0, false);
mNavBarAvailable = a.getBoolean(1, false);
} finally {
a.recycle();
}
// check window flags
WindowManager.LayoutParams winParams = win.getAttributes();
int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if ((winParams.flags & bits) != 0) {
mStatusBarAvailable = true;
}
bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
if ((winParams.flags & bits) != 0) {
mNavBarAvailable = true;
}
}
mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
// device might not have virtual navigation keys
if (!mConfig.hasNavigtionBar()) {
mNavBarAvailable = false;
}
if (mStatusBarAvailable) {
setupStatusBarView(activity, decorViewGroup);
}
if (mNavBarAvailable) {
setupNavBarView(activity, decorViewGroup);
}
}
/**
* Enable tinting of the system status bar.
*
* If the platform is running Jelly Bean or earlier, or translucent system
* UI modes have not been enabled in either the theme or via window flags,
* then this method does nothing.
*
* @param enabled True to enable tinting, false to disable it (default).
*/
public void setStatusBarTintEnabled(boolean enabled) {
mStatusBarTintEnabled = enabled;
if (mStatusBarAvailable) {
mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
}
/**
* Enable tinting of the system navigation bar.
*
* If the platform does not have soft navigation keys, is running Jelly Bean
* or earlier, or translucent system UI modes have not been enabled in either
* the theme or via window flags, then this method does nothing.
*
* @param enabled True to enable tinting, false to disable it (default).
*/
public void setNavigationBarTintEnabled(boolean enabled) {
mNavBarTintEnabled = enabled;
if (mNavBarAvailable) {
mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
}
/**
* Apply the specified color tint to all system UI bars.
*
* @param color The color of the background tint.
*/
public void setTintColor(int color) {
setStatusBarTintColor(color);
setNavigationBarTintColor(color);
}
/**
* Apply the specified drawable or color resource to all system UI bars.
*
* @param res The identifier of the resource.
*/
public void setTintResource(int res) {
setStatusBarTintResource(res);
setNavigationBarTintResource(res);
}
/**
* Apply the specified drawable to all system UI bars.
*
* @param drawable The drawable to use as the background, or null to remove it.
*/
public void setTintDrawable(Drawable drawable) {
setStatusBarTintDrawable(drawable);
setNavigationBarTintDrawable(drawable);
}
/**
* Apply the specified alpha to all system UI bars.
*
* @param alpha The alpha to use
*/
public void setTintAlpha(float alpha) {
setStatusBarAlpha(alpha);
setNavigationBarAlpha(alpha);
}
/**
* Apply the specified color tint to the system status bar.
*
* @param color The color of the background tint.
*/
public void setStatusBarTintColor(int color) {
if (mStatusBarAvailable) {
mStatusBarTintView.setBackgroundColor(color);
}
}
/**
* Apply the specified drawable or color resource to the system status bar.
*
* @param res The identifier of the resource.
*/
public void setStatusBarTintResource(int res) {
if (mStatusBarAvailable) {
mStatusBarTintView.setBackgroundResource(res);
}
}
/**
* Apply the specified drawable to the system status bar.
*
* @param drawable The drawable to use as the background, or null to remove it.
*/
@SuppressWarnings("deprecation")
public void setStatusBarTintDrawable(Drawable drawable) {
if (mStatusBarAvailable) {
mStatusBarTintView.setBackgroundDrawable(drawable);
}
}
/**
* Apply the specified alpha to the system status bar.
*
* @param alpha The alpha to use
*/
@TargetApi(11)
public void setStatusBarAlpha(float alpha) {
if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mStatusBarTintView.setAlpha(alpha);
}
}
/**
* Apply the specified color tint to the system navigation bar.
*
* @param color The color of the background tint.
*/
public void setNavigationBarTintColor(int color) {
if (mNavBarAvailable) {
mNavBarTintView.setBackgroundColor(color);
}
}
/**
* Apply the specified drawable or color resource to the system navigation bar.
*
* @param res The identifier of the resource.
*/
public void setNavigationBarTintResource(int res) {
if (mNavBarAvailable) {
mNavBarTintView.setBackgroundResource(res);
}
}
/**
* Apply the specified drawable to the system navigation bar.
*
* @param drawable The drawable to use as the background, or null to remove it.
*/
@SuppressWarnings("deprecation")
public void setNavigationBarTintDrawable(Drawable drawable) {
if (mNavBarAvailable) {
mNavBarTintView.setBackgroundDrawable(drawable);
}
}
/**
* Apply the specified alpha to the system navigation bar.
*
* @param alpha The alpha to use
*/
@TargetApi(11)
public void setNavigationBarAlpha(float alpha) {
if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mNavBarTintView.setAlpha(alpha);
}
}
/**
* Get the system bar configuration.
*
* @return The system bar configuration for the current device configuration.
*/
public SystemBarConfig getConfig() {
return mConfig;
}
/**
* Is tinting enabled for the system status bar?
*
* @return True if enabled, False otherwise.
*/
public boolean isStatusBarTintEnabled() {
return mStatusBarTintEnabled;
}
/**
* Is tinting enabled for the system navigation bar?
*
* @return True if enabled, False otherwise.
*/
public boolean isNavBarTintEnabled() {
return mNavBarTintEnabled;
}
private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {
mStatusBarTintView = new View(context);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
params.gravity = Gravity.TOP;
if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {
params.rightMargin = mConfig.getNavigationBarWidth();
}
mStatusBarTintView.setLayoutParams(params);
mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
mStatusBarTintView.setVisibility(View.GONE);
decorViewGroup.addView(mStatusBarTintView);
}
private void setupNavBarView(Context context, ViewGroup decorViewGroup) {
mNavBarTintView = new View(context);
LayoutParams params;
if (mConfig.isNavigationAtBottom()) {
params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());
params.gravity = Gravity.BOTTOM;
} else {
params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);
params.gravity = Gravity.RIGHT;
}
mNavBarTintView.setLayoutParams(params);
mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
mNavBarTintView.setVisibility(View.GONE);
decorViewGroup.addView(mNavBarTintView);
}
/**
* Class which describes system bar sizing and other characteristics for the current
* device configuration.
*
*/
public static class SystemBarConfig {
private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
private final boolean mTranslucentStatusBar;
private final boolean mTranslucentNavBar;
private final int mStatusBarHeight;
private final int mActionBarHeight;
private final boolean mHasNavigationBar;
private final int mNavigationBarHeight;
private final int mNavigationBarWidth;
private final boolean mInPortrait;
private final float mSmallestWidthDp;
private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
Resources res = activity.getResources();
mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
mSmallestWidthDp = getSmallestWidthDp(activity);
mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
mActionBarHeight = getActionBarHeight(activity);
mNavigationBarHeight = getNavigationBarHeight(activity);
mNavigationBarWidth = getNavigationBarWidth(activity);
mHasNavigationBar = (mNavigationBarHeight > 0);
mTranslucentStatusBar = translucentStatusBar;
mTranslucentNavBar = traslucentNavBar;
}
@TargetApi(14)
private int getActionBarHeight(Context context) {
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
}
return result;
}
@TargetApi(14)
private int getNavigationBarHeight(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
String key;
if (mInPortrait) {
key = NAV_BAR_HEIGHT_RES_NAME;
} else {
key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
}
return getInternalDimensionSize(res, key);
}
}
return result;
}
@TargetApi(14)
private int getNavigationBarWidth(Context context) {
Resources res = context.getResources();
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (hasNavBar(context)) {
return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
}
}
return result;
}
@TargetApi(14)
private boolean hasNavBar(Context context) {
Resources res = context.getResources();
int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
if (resourceId != 0) {
boolean hasNav = res.getBoolean(resourceId);
// check override flag (see static block)
if ("1".equals(sNavBarOverride)) {
hasNav = false;
} else if ("0".equals(sNavBarOverride)) {
hasNav = true;
}
return hasNav;
} else { // fallback
return !ViewConfiguration.get(context).hasPermanentMenuKey();
}
}
private int getInternalDimensionSize(Resources res, String key) {
int result = 0;
int resourceId = res.getIdentifier(key, "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
return result;
}
@SuppressLint("NewApi")
private float getSmallestWidthDp(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
} else {
// TODO this is not correct, but we don't really care pre-kitkat
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
float widthDp = metrics.widthPixels / metrics.density;
float heightDp = metrics.heightPixels / metrics.density;
return Math.min(widthDp, heightDp);
}
/**
* Should a navigation bar appear at the bottom of the screen in the current
* device configuration? A navigation bar may appear on the right side of
* the screen in certain configurations.
*
* @return True if navigation should appear at the bottom of the screen, False otherwise.
*/
public boolean isNavigationAtBottom() {
return (mSmallestWidthDp >= 600 || mInPortrait);
}
/**
* Get the height of the system status bar.
*
* @return The height of the status bar (in pixels).
*/
public int getStatusBarHeight() {
return mStatusBarHeight;
}
/**
* Get the height of the action bar.
*
* @return The height of the action bar (in pixels).
*/
public int getActionBarHeight() {
return mActionBarHeight;
}
/**
* Does this device have a system navigation bar?
*
* @return True if this device uses soft key navigation, False otherwise.
*/
public boolean hasNavigtionBar() {
return mHasNavigationBar;
}
/**
* Get the height of the system navigation bar.
*
* @return The height of the navigation bar (in pixels). If the device does not have
* soft navigation keys, this will always return 0.
*/
public int getNavigationBarHeight() {
return mNavigationBarHeight;
}
/**
* Get the width of the system navigation bar when it is placed vertically on the screen.
*
* @return The width of the navigation bar (in pixels). If the device does not have
* soft navigation keys, this will always return 0.
*/
public int getNavigationBarWidth() {
return mNavigationBarWidth;
}
/**
* Get the layout inset for any system UI that appears at the top of the screen.
*
* @param withActionBar True to include the height of the action bar, False otherwise.
* @return The layout inset (in pixels).
*/
public int getPixelInsetTop(boolean withActionBar) {
return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
}
/**
* Get the layout inset for any system UI that appears at the bottom of the screen.
*
* @return The layout inset (in pixels).
*/
public int getPixelInsetBottom() {
if (mTranslucentNavBar && isNavigationAtBottom()) {
return mNavigationBarHeight;
} else {
return 0;
}
}
/**
* Get the layout inset for any system UI that appears at the right of the screen.
*
* @return The layout inset (in pixels).
*/
public int getPixelInsetRight() {
if (mTranslucentNavBar && !isNavigationAtBottom()) {
return mNavigationBarWidth;
} else {
return 0;
}
}
}
}

View File

@ -1,203 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.manager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.StringUtil;
import android.os.Handler;
import android.os.HandlerThread;
/**线程管理类
* @author Lemon
* @use ThreadManager.getInstance().runThread(...);
* 在使用ThreadManager的Context被销毁前ThreadManager.getInstance().destroyThread(...);
* 在应用退出前ThreadManager.getInstance().finish();
*/
public class ThreadManager {
private static final String TAG = "ThreadManager";
private Map<String, ThreadBean> threadMap;
private ThreadManager() {
threadMap = new HashMap<String, ThreadBean>();
}
private static ThreadManager threadManager;
public static synchronized ThreadManager getInstance() {
if (threadManager == null) {
threadManager = new ThreadManager();
}
return threadManager;
}
/**运行线程
* @param name
* @param runnable
* @return
*/
public Handler runThread(String name, Runnable runnable) {
if (StringUtil.isNotEmpty(name, true) == false || runnable == null) {
Log.e(TAG, "runThread StringUtil.isNotEmpty(name, true) == false || runnable == null >> return");
return null;
}
name = StringUtil.getTrimedString(name);
Log.d(TAG, "\n runThread name = " + name);
Handler handler = getHandler(name);
if (handler != null) {
Log.w(TAG, "handler != null >> destroyThread(name);");
destroyThread(name);
}
HandlerThread thread = new HandlerThread(name);
thread.start();//创建一个HandlerThread并启动它
handler = new Handler(thread.getLooper());//使用HandlerThread的looper对象创建Handler
handler.post(runnable);//将线程post到Handler中
threadMap.put(name, new ThreadBean(name, thread, runnable, handler));
Log.d(TAG, "runThread added name = " + name + "; threadMap.size() = " + threadMap.size() + "\n");
return handler;
}
/**获取线程Handler
* @param name
* @return
*/
private Handler getHandler(String name) {
ThreadBean tb = getThread(name);
return tb == null ? null : tb.getHandler();
}
/**获取线程
* @param name
* @return
*/
private ThreadBean getThread(String name) {
return name == null ? null : threadMap.get(name);
}
/**销毁线程
* @param nameList
* @return
*/
public void destroyThread(List<String> nameList) {
if (nameList != null) {
for (String name : nameList) {
destroyThread(name);
}
}
}
/**销毁线程
* @param name
* @return
*/
public void destroyThread(String name) {
destroyThread(getThread(name));
}
/**销毁线程
* @param tb
* @return
*/
private void destroyThread(ThreadBean tb) {
if (tb == null) {
Log.e(TAG, "destroyThread tb == null >> return;");
return;
}
destroyThread(tb.getHandler(), tb.getRunnable());
if (tb.getName() != null) { // StringUtil.isNotEmpty(tb.getName(), true)) {
threadMap.remove(tb.getName());
}
}
/**销毁线程
* @param handler
* @param runnable
* @return
*/
public void destroyThread(Handler handler, Runnable runnable) {
if (handler == null || runnable == null) {
Log.e(TAG, "destroyThread handler == null || runnable == null >> return;");
return;
}
try {
handler.removeCallbacks(runnable);
} catch (Exception e) {
Log.e(TAG, "onDestroy try { handler.removeCallbacks(runnable);... >> catch : " + e.getMessage());
}
}
/**结束ThreadManager所有进程
*/
public void finish() {
threadManager = null;
if (threadMap == null || threadMap.keySet() == null) {
Log.d(TAG, "finish threadMap == null || threadMap.keySet() == null >> threadMap = null; >> return;");
threadMap = null;
return;
}
List<String> nameList = new ArrayList<String>(threadMap.keySet());//直接用Set在系统杀掉应用时崩溃
if (nameList != null) {
for (String name : nameList) {
destroyThread(name);
}
}
threadMap = null;
Log.d(TAG, "\n finish finished \n");
}
/**线程类
*/
private static class ThreadBean {
private String name;
@SuppressWarnings("unused")
private HandlerThread thread;
private Runnable runnable;
private Handler handler;
public ThreadBean(String name, HandlerThread thread, Runnable runnable, Handler handler) {
this.name = name;
this.thread = thread;
this.runnable = runnable;
this.handler = handler;
}
public String getName() {
return name;
}
public Runnable getRunnable() {
return runnable;
}
public Handler getHandler() {
return handler;
}
}
}

View File

@ -1,207 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.manager;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
/**时间刷新器
* @author Lemon
* @use TimeRefresher.getInstance().addTimeRefreshListener(...);
* 在使用TimeRefresher的Context被销毁前TimeRefresher.getInstance().removeTimeRefreshListener(...);
* 在应用退出前TimeRefresher.getInstance().finish();
*/
public class TimeRefresher {
private static final String TAG = "TimeRefresher";
/**回调接口
*/
public interface OnTimeRefreshListener {
void onTimerStart();
void onTimerRefresh();
void onTimerStop();
}
private Map<String, TimeRefresher.TimeHolder> refreshMap;
private TimeRefresher() {
refreshMap = new HashMap<String, TimeRefresher.TimeHolder>();
}
private static TimeRefresher timeRefresher;
public static TimeRefresher getInstance() {
if (timeRefresher == null) {
timeRefresher = new TimeRefresher();
}
return timeRefresher;
}
public boolean isContain(String tag) {
return tag != null && refreshMap != null && refreshMap.containsKey(tag);
}
public synchronized void addTimeRefreshListener(String tag, OnTimeRefreshListener listener) {
addTimeRefreshListener(tag, 1000, listener);
}
public synchronized void addTimeRefreshListener(String tag, long duration, OnTimeRefreshListener listener) {
if (duration > 0 && tag != null && listener != null) {
Log.d(TAG, "\n addTimeRefreshListener duration > 0 && tag = " + tag + " && listener != null >>");
if (refreshMap.containsKey(tag) && refreshMap.get(tag) != null) {
refreshMap.get(tag).startTimer();
Log.d(TAG, "refreshMap.containsKey(tag) && refreshMap.get(tag) != null >> refreshMap.get(tag).startTimer();");
} else {
refreshMap.put(tag, new TimeHolder(duration, listener));
Log.d(TAG, "addTimeRefreshListener added tag = ");
}
}
Log.d(TAG, "addTimeRefreshListener refreshMap.size() = " + refreshMap.size() + "\n");
}
/**
* @param tag
*/
public synchronized void startTimeRefreshListener(String tag) {
TimeHolder holder = refreshMap.get("" + tag);
if (holder != null) {
holder.startTimer();
Log.d(TAG, "startTimeRefreshListener started tag = " + tag);
}
}
/**
* @param tag
*/
public synchronized void stopTimeRefreshListener(String tag) {
TimeHolder holder = refreshMap.get("" + tag);
if (holder != null) {
holder.stopTimer();
Log.d(TAG, "stopTimeRefreshListener stopped tag = " + tag);
}
}
/**
* @param tag
*/
public synchronized void removeTimeRefreshListener(String tag) {
TimeHolder holder = refreshMap.get("" + tag);
if (holder != null) {
holder.stopTimer();
holder = null;
}
refreshMap.remove("" + tag);
Log.d(TAG, "removeTimeRefreshListener removed tag = " + tag);
}
/**完全结束Timer进程
*/
public void finish() {
timeRefresher = null;
if (refreshMap == null || refreshMap.size() <= 0) {
Log.d(TAG, "finish refreshMap == null || refreshMap.size() <= 0 >> return;");
return;
}
Set<String> tagSet = refreshMap.keySet();
if (tagSet != null) {
for (String tag : tagSet) {
removeTimeRefreshListener(tag);
}
}
refreshMap = null;
Log.d(TAG, "\n finish finished \n");
}
/**计时器holder
*/
@SuppressLint("HandlerLeak")
static class TimeHolder {
long duration = 1000;
OnTimeRefreshListener listener;
public TimeHolder(OnTimeRefreshListener listener) {
this(1000, listener);
}
public TimeHolder(long duration, OnTimeRefreshListener listener) {
this.duration = duration;
this.listener = listener;
startTimer();
}
Timer timer;
TimerTask task;
/**启动计时器
*/
public void startTimer() {
if (listener == null) {
Log.e(TAG, "startTimer listener == null >> return;");
return;
}
// Log.w(TAG, "startTimer<<<<<<<< " + TimeUtil.getTime(System.currentTimeMillis()));
stopTimer();
listener.onTimerStart();
if (timer == null) {
timer = new Timer(true);
}
if (task == null) {
task = new TimerTask(){
public void run() {
handler.sendEmptyMessage(0);
}
};
}
timer.schedule(task, 0, duration); //延时0ms后执行1000ms执行一次
// Log.w(TAG, "startTimer >>>>>>> " + TimeUtil.getTime(System.currentTimeMillis()));
}
/**停止计时器
*/
public void stopTimer() {
if (listener != null) {
listener.onTimerStop();
}
// Log.w(TAG, "stopTimer<<<<<<<< " + TimeUtil.getTime(System.currentTimeMillis()));
if (timer != null) {
timer.cancel();
timer = null;
}
if (task != null) {
task.cancel();
task = null;
}
// Log.w(TAG, "stopTimer>>>>>>> " + TimeUtil.getTime(System.currentTimeMillis()));
}
final Handler handler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
listener.onTimerRefresh();
}
};
}
}

View File

@ -1,22 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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.*/
/**
* 管理类所在包
*/
/**
* @author Lemon
* @use 通用使用方法XXManager.getInstance().xxMethod(...)或new XXManager(...).xxMethod(...)
*/
package zuo.biao.library.manager;

View File

@ -1,112 +0,0 @@
package zuo.biao.library.model;
import java.io.Serializable;
public class City implements Serializable {
private static final long serialVersionUID = 1L;
private String province;
private String city;
// private String number;
private String firstPY;
private String allPY;
private String allFristPY;
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
public City() {
// TODO Auto-generated constructor stub
}
public City(String province, String city,Double lat, Double lon) {
super();
this.province = province;
this.city = city;
// this.number = number;
// this.firstPY = firstPY;
// this.allPY = allPY;
// this.allFristPY = allFristPY;
this.latitude = lat;
this.longitude = lon;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
// public String getNumber() {
// return number;
// }
//
// public void setNumber(String number) {
// this.number = number;
// }
public String getFirstPY() {
return firstPY;
}
public void setFirstPY(String firstPY) {
this.firstPY = firstPY;
}
public String getAllPY() {
return allPY;
}
public void setAllPY(String allPY) {
this.allPY = allPY;
}
public String getAllFristPY() {
return allFristPY;
}
public void setAllFristPY(String allFristPY) {
this.allFristPY = allFristPY;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
@Override
public String toString() {
return "City [province=" + province + ", city=" + city
+ ", firstPY=" + firstPY + ", allPY=" + allPY
+ ", allFristPY=" + allFristPY + "]";
}
}

View File

@ -1,66 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.model;
import zuo.biao.library.base.BaseModel;
/**自定义Entry
* *java.util.Map.Entry是interfacenew Entry(...)不好用其它的Entry也不好用
* @author Lemon
* @param <K> key
* @param <V> value
* @use new Entry<K, V>(...)
* @warn K,V都需要基本类型时不建议使用判空麻烦不如新建一个Model
*/
public class Entry<K, V> extends BaseModel {
private static final long serialVersionUID = 1L;
public K key;
public V value;
public Entry() {
//default
}
public Entry(K key) {
this(key, null);
}
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
@Override
public boolean isCorrect() {
return key != null;
}
}

View File

@ -1,143 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.model;
/**GridPickerView初始化配置model
*@author Lemon
*@date 2015-7-23 上午12:54:01
*/
public class GridPickerConfig {
// private List<GridPickerItemBean> list;//list一般都会变 ,GridPickerView只允许一个list
private String tabSuffix;
private String selectedItemName;//可变
private int selectedItemPostion;//可变
private int numColumns;//第一次设置后就固定不变
private int maxShowRows;//第一次设置后就固定不变
// private int enableTextColor;
// private int unableTextColor;
//
// private int enableBackgroundColor;
// private int unableBackgroundColor;
public GridPickerConfig(String tabSuffix, String selectedItemName, int selectedItemPostion) {
this(tabSuffix, selectedItemName, selectedItemPostion, 3, 5);
}
public GridPickerConfig(String tabSuffix, String selectedItemName, int selectedItemPostion, int numColumns, int maxShowRows) {
this.tabSuffix = tabSuffix;
this.selectedItemName = selectedItemName;
this.selectedItemPostion = selectedItemPostion;
this.numColumns = numColumns;
this.maxShowRows = maxShowRows;
}
/**只允许通过这个方法修改数据
* @param selectedItemName
* @param selectedItemPostion
* @return
*/
public final GridPickerConfig set(String selectedItemName, int selectedItemPostion) {
return set(tabSuffix, selectedItemName, selectedItemPostion);
}
/**只允许通过这个方法修改数据
* @param tabSuffix
* @param selectedItemName
* @param selectedItemPostion
* @return
*/
public final GridPickerConfig set(String tabSuffix, String selectedItemName, int selectedItemPostion) {
this.tabSuffix = tabSuffix;
this.selectedItemName = selectedItemName;
this.selectedItemPostion = selectedItemPostion;
return this;
}
/**带后缀
* @return
*/
public String getTabName() {
return getSelectedItemName() + getTabSuffix();
}
public String getTabSuffix() {
return tabSuffix == null ? "" : tabSuffix;
}
public String getSelectedItemName() {
return selectedItemName == null ? "" : selectedItemName;
}
public int getSelectedItemPostion() {
return selectedItemPostion;
}
public int getNumColumns() {
return numColumns;
}
public int getMaxShowRows() {
return maxShowRows;
}
// /**设置颜色
// * @param enableTextColor
// * @param unableTextColor
// * @param enableBackgroundColor
// * @param unableBackgroundColor
// * @return
// */
// public final GridPickerConfig setColor(int enableTextColor, int unableTextColor, int enableBackgroundColor, int unableBackgroundColor) {
// this.enableTextColor = enableTextColor;
// this.unableTextColor = unableTextColor;
// this.enableBackgroundColor = enableBackgroundColor;
// this.unableBackgroundColor = unableBackgroundColor;
// return this;
// }
//
// public int getEnableTextColor() {
// return enableTextColor;
// }
// public GridPickerConfig setEnableTextColor(int enableTextColor) {
// this.enableTextColor = enableTextColor;
// return this;
// }
// public int getUnableTextColor() {
// return unableTextColor;
// }
// public GridPickerConfig setUnableTextColor(int unableTextColor) {
// this.unableTextColor = unableTextColor;
// return this;
// }
// public int getEnableBackgroundColor() {
// return enableBackgroundColor;
// }
// public GridPickerConfig setEnableBackgroundColor(int enableBackgroundColor) {
// this.enableBackgroundColor = enableBackgroundColor;
// return this;
// }
// public int getUnableBackgroundColor() {
// return unableBackgroundColor;
// }
// public GridPickerConfig setUnableBackgroundColor(int unableBackgroundColor) {
// this.unableBackgroundColor = unableBackgroundColor;
// return this;
// }
}

View File

@ -1,79 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.model;
import android.content.Intent;
/**菜单类
* @author Lemon
*/
public class Menu {
private String name;
private int imageRes;
private int operationType;
private Intent operationIntent;
private int intentCode;
public Menu() {
// TODO Auto-generated constructor stub
}
public Menu(String name) {
this();
this.name = name;
}
public Menu(String name, int imageRes) {
this(name);
this.imageRes = imageRes;
}
public Menu(String name, int imageRes, int intentCode) {
this(name, imageRes);
this.intentCode = intentCode;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageRes() {
return imageRes;
}
public void setImageRes(int imageRes) {
this.imageRes = imageRes;
}
public int getOperationType() {
return operationType;
}
public void setOperationType(int operationType) {
this.operationType = operationType;
}
public Intent getOperationIntent() {
return operationIntent;
}
public void setOperationIntent(Intent operationIntent) {
this.operationIntent = operationIntent;
}
public int getIntentCode() {
return intentCode;
}
public void setIntentCode(int intentCode) {
this.intentCode = intentCode;
}
}

View File

@ -1,28 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.model;
/**Http请求参数类
* @author Lemon
*/
public class Parameter extends Entry<String, Object> {
private static final long serialVersionUID = 1L;
public Parameter(String key, Object value) {
super(key, value);
}
}

View File

@ -1,25 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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.*/
/**
* 模型类所在包
*/
/**
* @author Lemon
* @use 通用使用方法
* XXBean xxb = new XXBean(...);
* xxb.setXX(...);
* xxb.getXX();
*/
package zuo.biao.library.model;

View File

@ -1,142 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import zuo.biao.library.R;
import zuo.biao.library.util.StringUtil;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**通用对话框类
* @author Lemon
* @use new AlertDialog(...).show();
*/
public class AlertDialog extends Dialog implements android.view.View.OnClickListener {
// private static final String TAG = "AlertDialog";
/**
* 自定义Dialog监听器
*/
public interface OnDialogButtonClickListener {
/**点击按钮事件的回调方法
* @param requestCode 传入的用于区分某种情况下的showDialog
* @param isPositive
*/
void onDialogButtonClick(int requestCode, boolean isPositive);
}
@SuppressWarnings("unused")
private Context context;
private String title;
private String message;
private String strPositive;
private String strNegative;
private boolean showNegativeButton = true;
private int requestCode;
private OnDialogButtonClickListener listener;
/**
* 带监听器参数的构造函数
*/
public AlertDialog(Context context, String title, String message, boolean showNegativeButton,
int requestCode, OnDialogButtonClickListener listener) {
super(context, R.style.MyDialog);
this.context = context;
this.title = title;
this.message = message;
this.showNegativeButton = showNegativeButton;
this.requestCode = requestCode;
this.listener = listener;
}
public AlertDialog(Context context, String title, String message, boolean showNegativeButton,
String strPositive, int requestCode, OnDialogButtonClickListener listener) {
super(context, R.style.MyDialog);
this.context = context;
this.title = title;
this.message = message;
this.showNegativeButton = showNegativeButton;
this.strPositive = strPositive;
this.requestCode = requestCode;
this.listener = listener;
}
public AlertDialog(Context context, String title, String message,
String strPositive, String strNegative, int requestCode, OnDialogButtonClickListener listener) {
super(context, R.style.MyDialog);
this.context = context;
this.title = title;
this.message = message;
this.strPositive = strPositive;
this.strNegative = strNegative;
this.requestCode = requestCode;
this.listener = listener;
}
private TextView tvTitle;
private TextView tvMessage;
private Button btnPositive;
private Button btnNegative;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alert_dialog);
setCanceledOnTouchOutside(true);
tvTitle = (TextView) findViewById(R.id.tvAlertDialogTitle);
tvMessage = (TextView) findViewById(R.id.tvAlertDialogMessage);
btnPositive = (Button) findViewById(R.id.btnAlertDialogPositive);
btnNegative = (Button) findViewById(R.id.btnAlertDialogNegative);
tvTitle.setVisibility(StringUtil.isNotEmpty(title, true) ? View.VISIBLE : View.GONE);
tvTitle.setText("" + StringUtil.getCurrentString());
if (StringUtil.isNotEmpty(strPositive, true)) {
btnPositive.setText(StringUtil.getCurrentString());
}
btnPositive.setOnClickListener(this);
if (showNegativeButton) {
if (StringUtil.isNotEmpty(strNegative, true)) {
btnNegative.setText(StringUtil.getCurrentString());
}
btnNegative.setOnClickListener(this);
} else {
btnNegative.setVisibility(View.GONE);
}
tvMessage.setText(StringUtil.getTrimedString(message));
}
@Override
public void onClick(final View v) {
if (v.getId() == R.id.btnAlertDialogPositive) {
listener.onDialogButtonClick(requestCode, true);
} else if (v.getId() == R.id.btnAlertDialogNegative) {
listener.onDialogButtonClick(requestCode, false);
}
dismiss();
}
}

View File

@ -1,179 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseView;
import zuo.biao.library.model.Menu;
import zuo.biao.library.util.CommonUtil;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**自定义嵌入式菜单View
* @author Lemon
* @use
* <br> BottomMenuView bottomMenuView = new BottomMenuView(context, resources, toBottomMenuWindowRequestCode);
* <br> bottomMenuView.bindView(menuList);
* <br> bottomMenuView.setOnMenuItemClickListener(onBottomMenuItemClickListener);
* <br> *具体参考.UserActivity
*/
public class BottomMenuView extends BaseView<List<Menu>> {
private static final String TAG = "BottomMenuView";
public interface OnBottomMenuItemClickListener{
void onBottomMenuItemClick(int intentCode);
}
private OnBottomMenuItemClickListener onBottomMenuItemClickListener;
public void setOnMenuItemClickListener(OnBottomMenuItemClickListener l) {
onBottomMenuItemClickListener = l;
}
private int toBottomMenuWindowRequestCode;
public BottomMenuView(Activity context, Resources resources, int toBottomMenuWindowRequestCode) {
super(context, resources);
this.toBottomMenuWindowRequestCode = toBottomMenuWindowRequestCode;
}
private LayoutInflater inflater;
public LinearLayout llBottomMenuViewMainItemContainer;
/**获取View
* @return
*/
@SuppressLint("InflateParams")
@Override
public View createView(LayoutInflater inflater) {
this.inflater = inflater;
convertView = inflater.inflate(R.layout.bottom_menu_view, null);
llBottomMenuViewMainItemContainer = (LinearLayout)
convertView.findViewById(R.id.llBottomMenuViewMainItemContainer);
return convertView;
}
@Override
public List<Menu> getData() {
return list;
}
private List<Menu> list;//传进来的数据
private ArrayList<String> moreMenuNameList;
private ArrayList<Integer> moreMenuIntentCodeList;
@Override
public void bindView(final List<Menu> menuList){
if (menuList == null || menuList.isEmpty()) {
Log.e(TAG, "bindView menuList == null || menuList.isEmpty() >> return;");
return;
}
this.list = menuList;
llBottomMenuViewMainItemContainer.removeAllViews();
final int mainItemCount = list.size() > 4 ? 3 : list.size();//不包括 更多 按钮
Menu fsb;
for (int i = 0; i < mainItemCount; i++) {
fsb = list.get(i);
if (fsb.getImageRes() > 0) {
addItem(false, i, fsb);
} else {
break;
}
}
//菜单区域外的背景及监听不好做还是点击更多弹出BottomMenuWindow好
if (list.size() > 4) {
addItem(true, -1, null);
//弹出底部菜单
moreMenuNameList = new ArrayList<String>();
moreMenuIntentCodeList = new ArrayList<Integer>();
Menu moreFsb;
for (int i = 3; i < list.size(); i++) {
moreFsb = list.get(i);
if (moreFsb != null) {
moreMenuNameList.add(moreFsb.getName());
moreMenuIntentCodeList.add(moreFsb.getIntentCode());
}
}
}
}
/**添加带图标的主要按钮
* @param position
* @param fsb
*/
@SuppressLint("InflateParams")
private void addItem(final boolean isMoreButton, final int position, final Menu fsb) {
if (isMoreButton == false) {
if (position < 0 || fsb == null || StringUtil.isNotEmpty(fsb.getName(), true) == false
|| fsb.getImageRes() <= 0) {
Log.e(TAG, "addItem isMoreButton == false >> position < 0 || fsb == null " +
"|| StringUtil.isNotEmpty(fsb.getName(), true) == false " +
"|| fsb.getImageRes() <= 0 >> return;");
return;
};
}
LinearLayout ll = (LinearLayout) inflater.inflate(R.layout.icon_name_item, null);
ImageView iv = (ImageView) ll.findViewById(R.id.ivIconNameIcon);
TextView tv = (TextView) ll.findViewById(R.id.tvIconNameName);
try {
iv.setImageResource(isMoreButton ? R.drawable.up2_light : fsb.getImageRes());
} catch (Exception e) {
Log.e(TAG, "addItem try {" +
" iv.setImageResource(fsb.getImageRes()); " + e.getMessage() + ">> return;");
return;
}
tv.setText(isMoreButton ? "更多" : "" + fsb.getName());
ll.setPadding(
(int) getDimension(R.dimen.common_item_left_tv_padding),
0,
(int) getDimension(R.dimen.common_item_right_img_padding_right),
0);
ll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isMoreButton) {
CommonUtil.toActivity(context, BottomMenuWindow.createIntent(context
, moreMenuNameList, moreMenuIntentCodeList)
.putExtra(BottomMenuWindow.INTENT_TITLE, "更多"), toBottomMenuWindowRequestCode, false);
} else {
onBottomMenuItemClickListener.onBottomMenuItemClick(fsb.getIntentCode());
}
}
});
llBottomMenuViewMainItemContainer.addView(ll, position);
}
}

View File

@ -1,282 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.ArrayList;
import java.util.Arrays;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseBottomWindow;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
/**通用底部弹出菜单
* @author Lemon
* @use
* <br> toActivity或startActivityForResult (BottomMenuWindow.createIntent(...), requestCode);
* <br> 然后在onActivityResult方法内
* <br> data.getIntExtra(BottomMenuWindow.RESULT_ITEM_ID); 可得到点击的 position
* <br>
* <br> data.getIntExtra(BottomMenuWindow.RESULT_INTENT_CODE); 可得到点击的 intentCode
*/
public class BottomMenuWindow extends BaseBottomWindow implements OnItemClickListener {
private static final String TAG = "BottomMenuWindow";
//启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**启动BottomMenuWindow的Intent
* @param context
* @param names
* @return
*/
public static Intent createIntent(Context context, String[] names) {
return createIntent(context, names, new ArrayList<Integer>());
}
/**启动BottomMenuWindow的Intent
* @param context
* @param nameList
* @return
*/
public static Intent createIntent(Context context, ArrayList<String> nameList) {
return createIntent(context, nameList, null);
}
/**启动BottomMenuWindow的Intent
* @param context
* @param names
* @param ids
* @return
*/
public static Intent createIntent(Context context, String[] names, int[] ids) {
return new Intent(context, BottomMenuWindow.class).
putExtra(INTENT_ITEMS, names).
putExtra(INTENT_ITEM_IDS, ids);
}
/**启动BottomMenuWindow的Intent
* @param context
* @param names
* @param idList
* @return
*/
public static Intent createIntent(Context context, String[] names, ArrayList<Integer> idList) {
return new Intent(context, BottomMenuWindow.class).
putExtra(INTENT_ITEMS, names).
putExtra(INTENT_ITEM_IDS, idList);
}
/**启动BottomMenuWindow的Intent
* @param context
* @param nameList
* @param idList
* @return
*/
public static Intent createIntent(Context context,
ArrayList<String> nameList, ArrayList<Integer> idList) {
return new Intent(context, BottomMenuWindow.class).
putStringArrayListExtra(INTENT_ITEMS, nameList).
putIntegerArrayListExtra(INTENT_ITEM_IDS, idList);
}
//启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
public Activity getActivity() {
return this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bottom_menu_window);
//功能归类分区方法必须调用<<<<<<<<<<
initView();
initData();
initEvent();
//功能归类分区方法必须调用>>>>>>>>>>
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private ListView lvBottomMenu;
@Override
public void initView() {//必须调用
super.initView();
lvBottomMenu = (ListView) findViewById(R.id.lvBottomMenu);
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private String title;
private ArrayList<String> nameList = null;
private ArrayList<Integer> idList = null;
private ArrayAdapter<String> adapter;
@Override
public void initData() {//必须调用
super.initData();
intent = getIntent();
title = intent.getStringExtra(INTENT_TITLE);
if (StringUtil.isNotEmpty(title, true)) {
tvBaseTitle.setVisibility(View.VISIBLE);
tvBaseTitle.setText(StringUtil.getCurrentString());
} else {
tvBaseTitle.setVisibility(View.GONE);
}
int[] ids = intent.getIntArrayExtra(INTENT_ITEM_IDS);
if (ids == null || ids.length <= 0) {
idList = intent.getIntegerArrayListExtra(INTENT_ITEM_IDS);
} else {
idList = new ArrayList<Integer>();
for (int id : ids) {
idList.add(id);
}
}
String[] menuItems = intent.getStringArrayExtra(INTENT_ITEMS);
if (menuItems == null || menuItems.length <= 0) {
nameList = intent.getStringArrayListExtra(INTENT_ITEMS);
} else {
nameList = new ArrayList<String>(Arrays.asList(menuItems));
}
if (nameList == null || nameList.size() <= 0) {
Log.e(TAG, "init nameList == null || nameList.size() <= 0 >> finish();return;");
finish();
return;
}
adapter = new ArrayAdapter<String>(this, R.layout.bottom_menu_item, R.id.tvBottomMenuItem, nameList);
lvBottomMenu.setAdapter(adapter);
}
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {//必须调用
super.initEvent();
lvBottomMenu.setOnItemClickListener(this);
vBaseBottomWindowRoot.setOnTouchListener(new OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
finish();
return true;
}
});
}
//系统自带监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
intent = new Intent()
.putExtra(RESULT_TITLE, StringUtil.getTrimedString(tvBaseTitle))
.putExtra(RESULT_ITEM_ID, position);
if (idList != null && idList.size() > position) {
intent.putExtra(RESULT_ITEM_ID, idList.get(position));
}
setResult(RESULT_OK, intent);
finish();
}
@Override
protected void setResult() {
}
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,297 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.io.File;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseActivity;
import zuo.biao.library.util.CommonUtil;
import zuo.biao.library.util.DataKeeper;
import zuo.biao.library.util.StringUtil;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
/**通用获取裁剪单张照片Activity
* @author Lemon
* @use
* <br> toActivity或startActivityForResult (CutPictureActivity.createIntent(...), requestCode);
* <br> 然后在onActivityResult方法内
* <br> data.getStringExtra(CutPictureActivity.RESULT_PICTURE_PATH); 可得到图片存储路径
*/
public class CutPictureActivity extends BaseActivity {
private static final String TAG = "CutPictureActivity";
//启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final String INTENT_ORIGINAL_PICTURE_PATH = "INTENT_ORIGINAL_PICTURE_PATH";
public static final String INTENT_CUTTED_PICTURE_PATH = "INTENT_CUTTED_PICTURE_PATH";
public static final String INTENT_CUTTED_PICTURE_NAME = "INTENT_CUTTED_PICTURE_NAME";
public static final String INTENT_CUT_WIDTH = "INTENT_CUT_WIDTH";
public static final String INTENT_CUT_HEIGHT = "INTENT_CUT_HEIGHT";
/**启动这个Activity的Intent
* @param context
* @param originalPath
* @param cuttedPath
* @param cuttedName
* @param cuttedSize
* @return
*/
public static Intent createIntent(Context context, String originalPath
, String cuttedPath, String cuttedName, int cuttedSize) {
return createIntent(context, originalPath, cuttedPath, cuttedName, cuttedSize, cuttedSize);
}
/**启动这个Activity的Intent
* @param context
* @param originalPath
* @param cuttedPath
* @param cuttedName
* @param cuttedWidth
* @param cuttedHeight
* @return
*/
public static Intent createIntent(Context context, String originalPath
, String cuttedPath, String cuttedName, int cuttedWidth, int cuttedHeight) {
Intent intent = new Intent(context, CutPictureActivity.class);
intent.putExtra(INTENT_ORIGINAL_PICTURE_PATH, originalPath);
intent.putExtra(INTENT_CUTTED_PICTURE_PATH, cuttedPath);
intent.putExtra(INTENT_CUTTED_PICTURE_NAME, cuttedName);
intent.putExtra(INTENT_CUT_WIDTH, cuttedWidth);
intent.putExtra(INTENT_CUT_HEIGHT, cuttedHeight);
return intent;
}
//启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
public Activity getActivity() {
return this;
}
private String originalPicturePath;
private String cuttedPicturePath;
private String cuttedPictureName;
private int cuttedWidth;
private int cuttedHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
intent = getIntent();
originalPicturePath = intent.getStringExtra(INTENT_ORIGINAL_PICTURE_PATH);
cuttedWidth = intent.getIntExtra(INTENT_CUT_WIDTH, 0);
cuttedHeight = intent.getIntExtra(INTENT_CUT_HEIGHT, 0);
if (cuttedWidth <= 0) {
cuttedWidth = cuttedHeight;
}
if (cuttedHeight <= 0) {
cuttedHeight = cuttedWidth;
}
if (StringUtil.isNotEmpty(originalPicturePath, true) == false || cuttedWidth <= 0) {
Log.e(TAG, "onCreate StringUtil.isNotEmpty(originalPicturePath, true)" +
" == false || cuttedWidth <= 0 >> finish(); return;");
showShortToast("图片不存在,请先选择图片");
finish();
return;
}
//功能归类分区方法必须调用<<<<<<<<<<
initData();
initView();
initEvent();
//功能归类分区方法必须调用>>>>>>>>>>
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initView() {//必须调用
}
/**照片裁剪
* @param path
* @param width
* @param height
*/
public void startPhotoZoom(String path, int width, int height) {
startPhotoZoom(Uri.fromFile(new File(path)), width, height);
}
/**照片裁剪
* @param fileUri
* @param width
* @param height
*/
public void startPhotoZoom(Uri fileUri, int width, int height) {
intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(fileUri, "image/*");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX,outputY 是剪裁图片的宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
if (Build.VERSION.SDK_INT >= 23) {
File outputImage = new File(DataKeeper.imagePath, "output_image" + System.currentTimeMillis() + ".jpg");
cuttedPicturePath = outputImage.getAbsolutePath();
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputImage));
} else {
intent.putExtra("crop", "true");// crop为true是设置在开启的intent中设置显示的view可以剪裁
intent.putExtra("return-data", true);
}
Log.i(TAG, "startPhotoZoom fileUri = "+ fileUri);
toActivity(intent, REQUEST_CUT_PHOTO);
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initData() {//必须调用
startPhotoZoom(originalPicturePath, cuttedWidth, cuttedHeight);
}
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {//必须调用
}
//系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final int REQUEST_CODE_CAMERA = 18;
public static final int REQUEST_CODE_LOCAL = 19;
public static final int REQUEST_CUT_PHOTO = 20;
public static final String RESULT_PICTURE_PATH = "RESULT_PICTURE_PATH";
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CUT_PHOTO: //发送本地图片
if (data != null) {
if (Build.VERSION.SDK_INT < 23 || new File(cuttedPicturePath).exists() == false) {
Bundle bundle = data.getExtras();
if (bundle != null) {
Bitmap photo = bundle.getParcelable("data");
//photo.
if (photo != null) {
//照片的路径
setCuttedPicturePath();
cuttedPicturePath = CommonUtil.savePhotoToSDCard(cuttedPicturePath, cuttedPictureName, "jpg", photo);
}
}
}
setResult(RESULT_OK, new Intent().putExtra(RESULT_PICTURE_PATH, cuttedPicturePath));
}
break;
default:
break;
}
}
finish();
}
private String setCuttedPicturePath() {
//oringlePicturePath 不对
cuttedPicturePath = intent.getStringExtra(INTENT_CUTTED_PICTURE_PATH);
if (StringUtil.isFilePath(cuttedPicturePath) == false) {
cuttedPicturePath = DataKeeper.fileRootPath + DataKeeper.imagePath;
}
cuttedPictureName = intent.getStringExtra(INTENT_CUTTED_PICTURE_NAME);
if (StringUtil.isFilePath(cuttedPictureName) == false) {
cuttedPictureName = "photo" + System.currentTimeMillis();
}
return cuttedPicturePath;
}
@Override
public void finish() {
exitAnim = enterAnim = R.anim.null_anim;
super.finish();
}
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,414 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import zuo.biao.library.base.BaseViewBottomWindow;
import zuo.biao.library.model.Entry;
import zuo.biao.library.model.GridPickerConfig;
import zuo.biao.library.ui.GridPickerView.OnTabClickListener;
import zuo.biao.library.util.StringUtil;
import zuo.biao.library.util.TimeUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.TextView;
/**日期选择窗口
* @author Lemon
* @use
* <br> toActivity或startActivityForResult (DatePickerWindow.createIntent(...), requestCode);
* <br> 然后在onActivityResult方法内
* <br> data.getLongExtra(DatePickerWindow.RESULT_TIME_IN_MILLIS); 可得到选中的日期
* @warn 和android系统SDK内一样month从0开始
*/
public class DatePickerWindow extends BaseViewBottomWindow<List<Entry<Integer, String>>, GridPickerView> {
private static final String TAG = "DatePickerWindow";
//启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final String INTENT_MIN_DATE = "INTENT_MIN_DATE";
public static final String INTENT_MAX_DATE = "INTENT_MAX_DATE";
public static final String INTENT_DEFAULT_DATE = "INTENT_DEFAULT_DATE";
public static final String RESULT_DATE = "RESULT_DATE";
public static final String RESULT_TIME_IN_MILLIS = "RESULT_TIME_IN_MILLIS";
public static final String RESULT_DATE_DETAIL_LIST = "RESULT_DATE_DETAIL_LIST";
/**启动这个Activity的Intent
* @param context
* @param limitYearMonthDay
* @return
*/
public static Intent createIntent(Context context, int[] limitYearMonthDay) {
return createIntent(context, limitYearMonthDay, null);
}
/**启动这个Activity的Intent
* @param context
* @param limitYearMonthDay
* @param defaultYearMonthDay
* @return
*/
public static Intent createIntent(Context context, int[] limitYearMonthDay, int[] defaultYearMonthDay) {
int[] selectedDate = TimeUtil.getDateDetail(System.currentTimeMillis());
int[] minYearMonthDay = null;
int[] maxYearMonthDay = null;
if (TimeUtil.fomerIsBigger(limitYearMonthDay, selectedDate)) {
minYearMonthDay = selectedDate;
maxYearMonthDay = limitYearMonthDay;
} else {
minYearMonthDay = limitYearMonthDay;
maxYearMonthDay = selectedDate;
}
return createIntent(context, minYearMonthDay, maxYearMonthDay, defaultYearMonthDay);
}
/**启动这个Activity的Intent
* @param context
* @param minYearMonthDay
* @param maxYearMonthDay
* @return
*/
public static Intent createIntent(Context context, int[] minYearMonthDay, int[] maxYearMonthDay, int[] defaultYearMonthDay) {
return new Intent(context, DatePickerWindow.class).
putExtra(INTENT_MIN_DATE, minYearMonthDay).
putExtra(INTENT_MAX_DATE, maxYearMonthDay).
putExtra(INTENT_DEFAULT_DATE, defaultYearMonthDay);
}
//启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
public Activity getActivity() {
return this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//功能归类分区方法必须调用<<<<<<<<<<
initView();
initData();
initEvent();
//功能归类分区方法必须调用>>>>>>>>>>
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initView() {//必须调用
super.initView();
}
private List<Entry<Integer, String>> list;
private void setPickerView(final int tabPosition) {
runThread(TAG + "setPickerView", new Runnable() {
@Override
public void run() {
final ArrayList<Integer> selectedItemList = new ArrayList<Integer>();
for (GridPickerConfig gpcb : configList) {
selectedItemList.add(0 + Integer.valueOf(StringUtil.getNumber(gpcb.getSelectedItemName())));
}
list = getList(tabPosition, selectedItemList);
runUiThread(new Runnable() {
@Override
public void run() {
containerView.bindView(tabPosition, list);
//防止选中非闰年2月29日
if (tabPosition < 2) {
ArrayList<String> selectedList = containerView.getSelectedItemList();
if (selectedList != null && selectedList.size() >= 3) {
if (TimeUtil.isLeapYear(0 + Integer.valueOf(
StringUtil.getNumber(selectedList.get(0)))) == false) {
if ("2".equals(StringUtil.getNumber(selectedList.get(1)))
&& "29".equals(StringUtil.getNumber(selectedList.get(2)))) {
onItemSelectedListener.onItemSelected(
null, null, containerView.getCurrentSelectedItemPosition(), 0);
}
}
}
}
}
});
}
});
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// private long minDate;
// private long maxDate;
private int[] minDateDetails;
private int[] maxDateDetails;
private int[] defaultDateDetails;
private ArrayList<GridPickerConfig> configList;
@Override
public void initData() {//必须调用
super.initData();
intent = getIntent();
// minDate = getIntent().getLongExtra(INTENT_MIN_DATE, 0);
// maxDate = getIntent().getLongExtra(INTENT_MAX_DATE, 0);
// if (minDate >= maxDate) {
// Log.e(TAG, "initData minDate >= maxDate >> finish(); return; ");
// finish();
// return;
// }
//
// int[] minDateDetails = TimeUtil.getDateDetail(minDate);
// int[] maxDateDetails = TimeUtil.getDateDetail(maxDate);
minDateDetails = intent.getIntArrayExtra(INTENT_MIN_DATE);
maxDateDetails = intent.getIntArrayExtra(INTENT_MAX_DATE);
defaultDateDetails = intent.getIntArrayExtra(INTENT_DEFAULT_DATE);
if (minDateDetails == null || minDateDetails.length <= 0) {
minDateDetails = new int[]{1970, 1, 1};
}
if (maxDateDetails == null || maxDateDetails.length <= 0) {
maxDateDetails = new int[]{2020, 11, 31};
}
if (minDateDetails == null || minDateDetails.length <= 0
|| maxDateDetails == null || minDateDetails.length != maxDateDetails.length) {
finish();
return;
}
if (defaultDateDetails == null || defaultDateDetails.length < 3) {
defaultDateDetails = TimeUtil.getDateDetail(System.currentTimeMillis());
}
runThread(TAG + "initData", new Runnable() {
@Override
public void run() {
final ArrayList<Integer> selectedItemList = new ArrayList<Integer>();
selectedItemList.add(defaultDateDetails[0]);
selectedItemList.add(defaultDateDetails[1]);
selectedItemList.add(defaultDateDetails[2]);
list = getList(selectedItemList.size() - 1, selectedItemList);
runUiThread(new Runnable() {
@Override
public void run() {
containerView.init(configList, list);
}
});
}
});
}
@SuppressLint("ResourceAsColor")
private synchronized List<Entry<Integer, String>> getList(int tabPosition, ArrayList<Integer> selectedItemList) {
int level = TimeUtil.LEVEL_YEAR + tabPosition;
if (selectedItemList == null || selectedItemList.size() != 3 || TimeUtil.isContainLevel(level) == false) {
return null;
}
list = new ArrayList<Entry<Integer, String>>();
Calendar calendar = Calendar.getInstance();
calendar.set(selectedItemList.get(0), selectedItemList.get(1) - 1, 1);
switch (level) {
case TimeUtil.LEVEL_YEAR:
for (int i = 0; i < maxDateDetails[0] - minDateDetails[0]; i++) {
list.add(new Entry<Integer, String>(GridPickerAdapter.TYPE_CONTNET_ENABLE, String.valueOf(i + 1 + minDateDetails[0])));
}
break;
case TimeUtil.LEVEL_MONTH:
for (int i = 0; i < 12; i++) {
list.add(new Entry<Integer, String>(GridPickerAdapter.TYPE_CONTNET_ENABLE, String.valueOf(i + 1)));
}
break;
case TimeUtil.LEVEL_DAY:
for (int i = calendar.get(Calendar.DAY_OF_WEEK) - 1; i < 7; i++) {
list.add(new Entry<Integer, String>(GridPickerAdapter.TYPE_TITLE, TimeUtil.Day.getDayNameOfWeek(i)));
}
for (int i = 0; i < calendar.get(Calendar.DAY_OF_WEEK) - 1; i++) {
list.add(new Entry<Integer, String>(GridPickerAdapter.TYPE_TITLE, TimeUtil.Day.getDayNameOfWeek(i)));
}
for (int i = 0; i < calendar.getActualMaximum(Calendar.DATE); i++) {
list.add(new Entry<Integer, String>(GridPickerAdapter.TYPE_CONTNET_ENABLE, String.valueOf(i + 1)));
}
break;
default:
break;
}
if (configList == null || configList.size() < 3) {
configList = new ArrayList<GridPickerConfig>();
configList.add(new GridPickerConfig(TimeUtil.NAME_YEAR, "" + selectedItemList.get(0)
, selectedItemList.get(0) - 1 - minDateDetails[0], 5, 4));
configList.add(new GridPickerConfig(TimeUtil.NAME_MONTH, "" + selectedItemList.get(1)
, selectedItemList.get(1) - 1, 4, 3));
configList.add(new GridPickerConfig(TimeUtil.NAME_DAY, "" + selectedItemList.get(2)
, selectedItemList.get(2) - 1 + 7, 7, 6));
}
return list;
}
@Override
public String getTitleName() {
return "选择日期";
}
@Override
public String getReturnName() {
return null;
}
@Override
public String getForwardName() {
return null;
}
@Override
protected GridPickerView createView() {
return new GridPickerView(context, getResources());
}
@Override
protected void setResult() {
intent = new Intent();
List<String> list = containerView.getSelectedItemList();
if (list != null && list.size() >= 3) {
ArrayList<Integer> detailList = new ArrayList<Integer>();
for (int i = 0; i < list.size(); i++) {
detailList.add(0 + Integer.valueOf(StringUtil.getNumber(list.get(i))));
}
detailList.set(1, detailList.get(1) - 1);
Calendar calendar = Calendar.getInstance();
calendar.set(detailList.get(0), detailList.get(1), detailList.get(2));
intent.putExtra(RESULT_TIME_IN_MILLIS, calendar.getTimeInMillis());
intent.putIntegerArrayListExtra(RESULT_DATE_DETAIL_LIST, detailList);
}
setResult(RESULT_OK, intent);
}
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void initEvent() {//必须调用
super.initEvent();
containerView.setOnTabClickListener(onTabClickListener);
containerView.setOnItemSelectedListener(onItemSelectedListener);
}
private OnTabClickListener onTabClickListener = new OnTabClickListener() {
@Override
public void onTabClick(int tabPosition, TextView tvTab) {
setPickerView(tabPosition);
}
};
private OnItemSelectedListener onItemSelectedListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, final int position, long id) {
containerView.doOnItemSelected(containerView.getCurrentTabPosition()
, position, containerView.getCurrentSelectedItemName());
int tabPosition = containerView.getCurrentTabPosition() + 1;
setPickerView(tabPosition);
}
@Override
public void onNothingSelected(AdapterView<?> parent) { }
};
//系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,460 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseActivity;
import zuo.biao.library.interfaces.OnBottomDragListener;
import zuo.biao.library.util.EditTextUtil;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
/**通用编辑个人资料文本界面
* @author Lemon
* @use
* <br> toActivity或startActivityForResult (EditTextInfoActivity.createIntent(...), requestCode);
* <br> 然后在onActivityResult方法内
* <br> data.getStringExtra(EditTextInfoActivity.RESULT_EDIT_TEXT_INFO); 可得到输入框内容
*/
public class EditTextInfoActivity extends BaseActivity implements OnBottomDragListener {
public static final String TAG = "EditTextInfoActivity";
//启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final String RESULT_TYPE = "RESULT_TYPE";
public static final String RESULT_KEY = "RESULT_KEY";
public static final String RESULT_VALUE = "RESULT_VALUE";
public static final String RESULT_URL = "RESULT_URL";
public static final String RESULT_ID = "RESULT_ID";
public static final String RESULT_IMAGE_URL = "RESULT_IMAGE_URL";
/**
* @param context
* @param key
* @param value
* @return
*/
public static Intent createIntent(Context context, String key, String value) {
return createIntent(context, 0, key, value);
}
/**
* @param context
* @param type
* @param key
* @param value
* @return
*/
public static Intent createIntent(Context context, int type, String key, String value) {
return new Intent(context, EditTextInfoActivity.class).
putExtra(INTENT_TYPE, type).
putExtra(INTENT_KEY, key).
putExtra(INTENT_VALUE, value);
}
//启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
public Activity getActivity() {
return this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_info_activity, this);//传this是为了全局滑动返回
//必须调用<<<<<<<<<<<
initView();
initData();
initEvent();
//必须调用>>>>>>>>>>
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private EditText etEditTextInfo;
private View ivEditTextInfoClear;
private TextView tvEditTextInfoRemind;
private ListView lvEditTextInfo;
// private XListView lvEditTextInfo;
@Override
public void initView() {//必须调用
etEditTextInfo = (EditText) findViewById(R.id.etEditTextInfo);
ivEditTextInfoClear = findViewById(R.id.ivEditTextInfoClear);
tvEditTextInfoRemind = (TextView) findViewById(R.id.tvEditTextInfoRemind);
lvEditTextInfo = (ListView) findViewById(R.id.lvEditTextInfo);
}
private ArrayAdapter<String> adapter;
/**显示列表内容
* @author author
* @param list
*/
private void setList(List<String> list) {
if (hasList == false || list == null || list.size() <= 0) {
Log.i(TAG, "setList list == null || list.size() <= 0 >> adapter = null;lvEditTextInfo.setAdapter(null); return;");
adapter = null;
lvEditTextInfo.setAdapter(null);
return;
}
adapter = new ArrayAdapter<String>(context, R.layout.list_item, R.id.tvListItem, list);
lvEditTextInfo.setAdapter(adapter);
// if (hasUrl) {
// }
lvEditTextInfo.smoothScrollBy(60, 200);
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final int TYPE_NICK = EditTextInfoWindow.TYPE_NICK;
public static final int TYPE_NAME = EditTextInfoWindow.TYPE_NAME;
public static final int TYPE_PHONE = EditTextInfoWindow.TYPE_PHONE;
public static final int TYPE_WEBSITE = EditTextInfoWindow.TYPE_WEBSITE;
public static final int TYPE_EMAIL = EditTextInfoWindow.TYPE_EMAIL;
public static final int TYPE_FAX = EditTextInfoWindow.TYPE_FAX;
public static final int TYPE_USUALADDRESS = EditTextInfoWindow.TYPE_USUALADDRESS;
public static final int TYPE_MAILADDRESS = EditTextInfoWindow.TYPE_MAILADDRESS;
public static final int TYPE_SCHOOL = EditTextInfoWindow.TYPE_SCHOOL;
public static final int TYPE_COMPANY = EditTextInfoWindow.TYPE_COMPANY;
public static final int TYPE_PROFESSION = EditTextInfoWindow.TYPE_PROFESSION;
public static final int TYPE_NOTE = EditTextInfoWindow.TYPE_NOTE;
// public static final int TYPE_OTHER = EditTextInfoWindow.TYPE_OTHER;
public static final String INTENT_TYPE = EditTextInfoWindow.INTENT_TYPE;
public static final String INTENT_KEY = EditTextInfoWindow.INTENT_KEY;
public static final String INTENT_VALUE = EditTextInfoWindow.INTENT_VALUE;
private int intentType = 0;
private int maxEms = 30;
private boolean hasList = false;
private boolean hasUrl = false;
private ArrayList<String> list;
@Override
public void initData() {//必须调用
intent = getIntent();
intentType = intent.getIntExtra(INTENT_TYPE, 0);
if (StringUtil.isNotEmpty(intent.getStringExtra(INTENT_KEY), true)) {
tvBaseTitle.setText(StringUtil.getCurrentString());
}
etEditTextInfo.setSingleLine(intentType != TYPE_NOTE);
switch (intentType) {
case TYPE_NICK:
maxEms = 20;
break;
case TYPE_PHONE:
etEditTextInfo.setInputType(InputType.TYPE_CLASS_PHONE);
maxEms = 11;
break;
case TYPE_EMAIL:
etEditTextInfo.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
maxEms = 60;
break;
case TYPE_WEBSITE:
etEditTextInfo.setInputType(InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
maxEms = 200;
break;
case TYPE_MAILADDRESS:
maxEms = 60;
break;
case TYPE_PROFESSION:
tvEditTextInfoRemind.setText("所属行业");
maxEms = 15;
case TYPE_NOTE:
maxEms = 100;
break;
default:
break;
}
etEditTextInfo.setMaxEms(maxEms);
tvEditTextInfoRemind.setText("" + maxEms/2 + "个字(或" + maxEms + "个字符)");
getList(intentType);
}
private int requestSize = 20;
/**获取列表
* @author lemon
* @param listType
* @return
*/
protected void getList(final int listType) {
if (hasList == false) {
return;
}
list = new ArrayList<String>();
runThread(TAG + "getList", new Runnable() {
@Override
public void run() {
Log.i(TAG, "getList listType = " + listType);
if (listType == TYPE_PROFESSION) {
list = new ArrayList<String>(Arrays.asList(context.getResources().getStringArray(R.array.profesions)));
}
runUiThread(new Runnable() {
@Override
public void run() {
dismissProgressDialog();
if (hasList) {
setList(list);
}
}
});
}
});
}
private void saveAndExit() {
String editedValue = StringUtil.getTrimedString(etEditTextInfo);
if (editedValue.equals("" + getIntent().getStringExtra(INTENT_VALUE))) {
showShortToast("内容没有改变哦~");
} else {
intent = new Intent();
intent.putExtra(RESULT_TYPE, getIntent().getIntExtra(INTENT_TYPE, -1));
// intent.putExtra(RESULT_TYPE, StringUtil.getTrimedString(etEditTextInfo));
// intent.putExtra(RESULT_KEY, StringUtil.getTrimedString(etEditTextInfo));
intent.putExtra(RESULT_VALUE, editedValue);
setResult(RESULT_OK, intent);
exitAnim = R.anim.left_push_out;
finish();
}
}
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private String inputedString;
private static final long SEARCH_DELAY_TIME = 240;
private Handler searchHandler;
@Override
public void initEvent() {//必须调用
searchHandler = new Handler(new Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg == null) {
Log.e(TAG, "searchHandler handleMessage (msg == null >> return false;");
return false;
}
Log.i(TAG, "inputedString = " + inputedString + "msg.obj = " + msg.obj);
if(inputedString != null){
if (inputedString.equals(msg.obj)) {
getList(intentType);
}
}
return false;
}
});
etEditTextInfo.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
inputedString = StringUtil.getTrimedString(s);
if (StringUtil.isNotEmpty(inputedString, true) == false) {
ivEditTextInfoClear.setVisibility(View.GONE);
} else {
ivEditTextInfoClear.setVisibility(View.VISIBLE);
if (hasUrl == true) {
Message msg = new Message();
msg.obj = inputedString;
searchHandler.sendMessageDelayed(msg , SEARCH_DELAY_TIME);
}
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
ivEditTextInfoClear.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
etEditTextInfo.setText("");
}
});
etEditTextInfo.setText(StringUtil.getTrimedString(getIntent().getStringExtra(INTENT_VALUE)));
etEditTextInfo.setSelection(StringUtil.getLength(etEditTextInfo, true));
if (hasList == true) {
EditTextUtil.hideKeyboard(context, etEditTextInfo);
if (hasUrl) {
lvEditTextInfo.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (adapter != null && lvEditTextInfo.getLastVisiblePosition() >= adapter.getCount() - 1) {
requestSize += 20;
Log.i(TAG, "initEvent lvEditTextInfo.setOnScrollListener( >> onScroll getList(intentType);requestSize = " + requestSize);
getList(intentType);
}
}
});
// } else {
}
lvEditTextInfo.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// if (hasUrl) {
// position -= lvEditTextInfo.getHeaderViewsCount();
// }
if (position < adapter.getCount()) {
etEditTextInfo.setText("" + adapter.getItem(position));
if (hasUrl) {
intent = new Intent();
intent.putExtra(RESULT_TYPE, getIntent().getIntExtra(INTENT_TYPE, -1));
intent.putExtra(RESULT_KEY, getIntent().getStringExtra(INTENT_KEY));
intent.putExtra(RESULT_VALUE, adapter.getItem(position));
setResult(RESULT_OK, intent);
finish();
return;
}
saveAndExit();
}
}
});
lvEditTextInfo.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
EditTextUtil.hideKeyboard(context, etEditTextInfo);
return false;
}
});
}
}
@Override
public void onDragBottom(boolean rightToLeft) {
if (rightToLeft) {
saveAndExit();
return;
}
finish();
}
@Override
public void onForwardClick(View v) {
if (hasUrl == false) {
onDragBottom(true);
} else {
Message msg = new Message();
msg.obj = inputedString;
searchHandler.sendMessage(msg);
}
}
//系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void finish() {
super.finish();
EditTextUtil.hideKeyboard(context, etEditTextInfo);
}
//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,380 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseBottomWindow;
import zuo.biao.library.util.CommonUtil;
import zuo.biao.library.util.ContactUtil;
import zuo.biao.library.util.EditTextUtil;
import zuo.biao.library.util.StringUtil;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
/**通用编辑个人资料文本界面
* @author Lemon
* @use
* <br> toActivity或startActivityForResult (EditTextInfoWindow.createIntent(...), requestCode);
* <br> 然后在onActivityResult方法内
* <br> data.getStringExtra(EditTextInfoWindow.RESULT_EDIT_TEXT_INFO); 可得到输入框内容
*/
public class EditTextInfoWindow extends BaseBottomWindow implements OnClickListener {
// private static final String TAG = "EditTextInfoWindow";
/**
* @param context
* @param key
* @param value
* @return
*/
public static Intent createIntent(Context context, String key, String value) {
return createIntent(context, key, value, "zuo.biao.library");
}
/**
* @param context
* @param key
* @param value
* @param packageName
* @return
*/
public static Intent createIntent(Context context, String key, String value, String packageName) {
return createIntent(context, 0, key, value, packageName);
}
/**
* @param context
* @param type
* @param key
* @param value
* @return
*/
public static Intent createIntent(Context context, int type, String key, String value) {
return createIntent(context, type, key, value, "zuo.biao.library");
}
/**
* @param context
* @param type
* @param key
* @param value
* @param packageName type == TYPE_MAILADDRESS || type == TYPE_USUALADDRESS时必须不为空
* @return
*/
public static Intent createIntent(Context context, int type, String key, String value, String packageName) {
return new Intent(context, EditTextInfoWindow.class).
putExtra(INTENT_TYPE, type).
putExtra(INTENT_KEY, key).
putExtra(INTENT_VALUE, value).
putExtra(INTENT_PACKAGE_NAME, packageName);
}
@Override
public Activity getActivity() {
return this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_text_info_window);
//必须调用<<<<<<<<<<<
initView();
initData();
initEvent();
//必须调用>>>>>>>>>>
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private TextView tvEditTextInfoPlace;
private EditText etEditTextInfo;
private View ivEditTextInfoClear;
private TextView tvEditTextInfoRemind;
@Override
public void initView() {//必须调用
super.initView();
tvEditTextInfoPlace = (TextView) findViewById(R.id.tvEditTextInfoPlace);
tvEditTextInfoPlace.setVisibility(View.GONE);
etEditTextInfo = (EditText) findViewById(R.id.etEditTextInfo);
ivEditTextInfoClear = findViewById(R.id.ivEditTextInfoClear);
tvEditTextInfoRemind = (TextView) findViewById(R.id.tvEditTextInfoRemind);
}
//UI显示区(操作UI但不存在数据获取或处理代码也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final String INTENT_PACKAGE_NAME = "INTENT_PACKAGE_NAME";
public static final int TYPE_NICK = ContactUtil.TYPE_NICK;
public static final int TYPE_NAME = ContactUtil.TYPE_NAME;
public static final int TYPE_PHONE = ContactUtil.TYPE_PHONE;
public static final int TYPE_WEBSITE = ContactUtil.TYPE_WEBSITE;
public static final int TYPE_EMAIL = ContactUtil.TYPE_EMAIL;
public static final int TYPE_FAX = ContactUtil.TYPE_FAX;
public static final int TYPE_USUALADDRESS = ContactUtil.TYPE_USUALADDRESS;
public static final int TYPE_MAILADDRESS = ContactUtil.TYPE_MAILADDRESS;
public static final int TYPE_SCHOOL = ContactUtil.TYPE_SCHOOL;
public static final int TYPE_COMPANY = ContactUtil.TYPE_COMPANY;
public static final int TYPE_PROFESSION = ContactUtil.TYPE_PROFESSION;
public static final int TYPE_NOTE = ContactUtil.TYPE_NOTE;
// public static final int TYPE_OTHER = ContactUtil.TYPE_OTHER;
public static final int TYPE_NUMBER = 21;
public static final int TYPE_DECIMAL = 22;
public static final String INTENT_TYPE = "INTENT_TYPE";
public static final String INTENT_KEY = "INTENT_KEY";
public static final String INTENT_VALUE = "INTENT_VALUE";
private String packageName;
private int intentType = 0;
private int maxEms = 30;
@Override
public void initData() {//必须调用
super.initData();
intent = getIntent();
packageName = intent.getStringExtra(INTENT_PACKAGE_NAME);
intentType = intent.getIntExtra(INTENT_TYPE, 0);
if (StringUtil.isNotEmpty(intent.getStringExtra(INTENT_KEY), true)) {
tvBaseTitle.setText(StringUtil.getCurrentString());
}
etEditTextInfo.setSingleLine(intentType != TYPE_NOTE);
switch (intentType) {
case TYPE_NICK:
maxEms = 20;
break;
case TYPE_PHONE:
maxEms = 11;
etEditTextInfo.setInputType(InputType.TYPE_CLASS_PHONE);
break;
case TYPE_EMAIL:
maxEms = 60;
etEditTextInfo.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
break;
case TYPE_WEBSITE:
maxEms = 200;
etEditTextInfo.setInputType(InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
break;
case TYPE_MAILADDRESS:
maxEms = 60;
break;
case TYPE_PROFESSION:
tvEditTextInfoRemind.setText("所属行业");
maxEms = 15;
case TYPE_NOTE:
maxEms = 100;
break;
case TYPE_NUMBER:
maxEms = 10;
etEditTextInfo.setInputType(InputType.TYPE_NUMBER_VARIATION_NORMAL);
break;
case TYPE_DECIMAL:
maxEms = 20;
etEditTextInfo.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
break;
default:
break;
}
etEditTextInfo.setMaxEms(maxEms);
tvEditTextInfoRemind.setText("" + maxEms/2 + "个字(或" + maxEms + "个字符)");
if (intentType == TYPE_MAILADDRESS || intentType == TYPE_USUALADDRESS) {
tvEditTextInfoPlace.setVisibility(View.VISIBLE);
CommonUtil.toActivity(context, PlacePickerWindow.createIntent(
context, packageName, 2), REQUEST_TO_PLACE_PICKER, false);
}
}
@Override
protected void setResult() {
intent = new Intent();
intent.putExtra(RESULT_TYPE, getIntent().getIntExtra(INTENT_TYPE, -1));
intent.putExtra(RESULT_KEY, getIntent().getStringExtra(INTENT_KEY));
intent.putExtra(RESULT_VALUE, editedValue);
setResult(RESULT_OK, intent);
}
//Data数据区(存在数据获取或处理代码但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private String inputedString;
@Override
public void initEvent() {//必须调用
super.initEvent();
tvEditTextInfoPlace.setOnClickListener(this);
etEditTextInfo.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
inputedString = StringUtil.getTrimedString(s);
if (StringUtil.isNotEmpty(inputedString, true) == false) {
ivEditTextInfoClear.setVisibility(View.GONE);
} else {
ivEditTextInfoClear.setVisibility(View.VISIBLE);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
ivEditTextInfoClear.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
etEditTextInfo.setText("");
}
});
etEditTextInfo.setText(StringUtil.getTrimedString(getIntent().getStringExtra(INTENT_VALUE)));
etEditTextInfo.setSelection(StringUtil.getLength(etEditTextInfo, true));
}
private String editedValue;
@Override
public void onForwardClick(View v) {
editedValue = StringUtil.getTrimedString(tvEditTextInfoPlace) + StringUtil.getTrimedString(etEditTextInfo);
if (editedValue.equals("" + getIntent().getStringExtra(INTENT_VALUE))) {
CommonUtil.showShortToast(context, "内容没有改变哦~");
return;
}
super.onForwardClick(v);
}
//系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public static final String RESULT_TYPE = "RESULT_TYPE";
public static final String RESULT_KEY = "RESULT_KEY";
public static final String RESULT_VALUE = "RESULT_VALUE";
public static final String RESULT_URL = "RESULT_URL";
public static final String RESULT_ID = "RESULT_ID";
public static final String RESULT_IMAGE_URL = "RESULT_IMAGE_URL";
@Override
public void onClick(View v) {
if (v.getId() == R.id.tvEditTextInfoPlace) {
CommonUtil.toActivity(context, PlacePickerWindow.createIntent(
context, packageName, 2), REQUEST_TO_PLACE_PICKER, false);
}
}
//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void finish() {
super.finish();
EditTextUtil.hideKeyboard(context, etEditTextInfo);
}
public static final int REQUEST_TO_PLACE_PICKER = 11;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case REQUEST_TO_PLACE_PICKER:
List<String> list = data == null ? null : data.getStringArrayListExtra(PlacePickerWindow.RESULT_PLACE_LIST);
if (list == null || list.size() < 2) {
CommonUtil.showShortToast(context, "请先选择地址哦~");
CommonUtil.toActivity(context, PlacePickerWindow.createIntent(
context, packageName, 2), REQUEST_TO_PLACE_PICKER, false);
return;
}
String place = "";
for (String s : list) {
place += s;
}
tvEditTextInfoPlace.setText(place);
break;
default:
break;
}
}
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,283 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import zuo.biao.library.R;
import zuo.biao.library.util.StringUtil;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;
/**通用密码手机号验证码输入框输入字符判断及错误提示
* @author Lemon
* @use EditTextManager.xxxMethod(...);
*/
public class EditTextManager {
private static final String TAG = "EditTextManager";
//显示/隐藏输入法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private static InputMethodManager imm;
/**隐藏输入法
* @param context
* @param toGetWindowTokenView
*/
public static void hideKeyboard(Context context, View toGetWindowTokenView){
showKeyboard(context, null, toGetWindowTokenView, false);
}
/**显示输入法
* @param context
* @param et
*/
public static void showKeyboard(Context context, EditText et){
showKeyboard(context, et, true);
}
/**显示/隐藏输入法
* @param context
* @param et
* @param show
*/
public static void showKeyboard(Context context, EditText et, boolean show){
showKeyboard(context, et, null, show);
}
/**显示输入法
* @param context
* @param et
* @param toGetWindowTokenView(为null时toGetWindowTokenView = et) 包含et的父View键盘根据toGetWindowTokenView的位置来弹出/隐藏
*/
public static void showKeyboard(Context context, EditText et, View toGetWindowTokenView) {
showKeyboard(context, et, toGetWindowTokenView, true);
}
/**显示/隐藏输入法
* @param context
* @param et
* @param toGetWindowTokenView(为null时toGetWindowTokenView = et) 包含et的父View键盘根据toGetWindowTokenView的位置来弹出/隐藏
* @param show
*/
public static void showKeyboard(Context context, EditText et, View toGetWindowTokenView, boolean show){
if (context == null) {
Log.e(TAG, "showKeyboard context == null >> return;");
return;
}
imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);//imm必须与context唯一对应
if (toGetWindowTokenView == null) {
Log.w(TAG, "showKeyboard toGetWindowTokenView == null");
toGetWindowTokenView = et;
}
if (toGetWindowTokenView == null) {
Log.e(TAG, "showKeyboard toGetWindowTokenView == null && et == null >> return;");
return;
}
if (show == false) {
imm.hideSoftInputFromWindow(toGetWindowTokenView.getWindowToken(), 0);
if (et != null) {
et.clearFocus();
}
} else {
if (et != null) {
et.setFocusable(true);
et.setFocusableInTouchMode(true);
et.requestFocus();
imm.toggleSoftInputFromWindow(toGetWindowTokenView.getWindowToken()
, InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
}
}
//显示/隐藏输入法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//对输入字符判断<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public final static int TYPE_NOT_ALLOWED_EMPTY = 0;
public final static int TYPE_VERIFY = 1;
public final static int TYPE_PASSWORD = 2;
public final static int TYPE_PHONE = 3;
public final static int TYPE_MAIL = 4;
private static ColorStateList oringinalHintColor;
/**判断edittext输入文字是否合法
* @param context
* @param et
* @return
*/
public static boolean isInputedCorrect(Activity context, EditText et) {
return isInputedCorrect(context, et, TYPE_NOT_ALLOWED_EMPTY, null);
}
/**判断edittext输入文字是否合法
* @param context
* @param et
* @param errorRemind
* @return
*/
public static boolean isInputedCorrect(Activity context, EditText et, String errorRemind) {
return isInputedCorrect(context, et, TYPE_NOT_ALLOWED_EMPTY, errorRemind);
}
/**判断edittext输入文字是否合法
* @param context
* @param et
* @param type
* @return
*/
public static boolean isInputedCorrect(Activity context, EditText et, int type) {
return isInputedCorrect(context, et, type, null);
}
/**判断edittext输入文字是否合法
* @param context
* @param stringResId
* @param et
* @return
*/
public static boolean isInputedCorrect(Activity context, int stringResId, EditText et) {
return isInputedCorrect(context, et, TYPE_NOT_ALLOWED_EMPTY, stringResId);
}
/**判断edittext输入文字是否合法
* @param context
* @param et
* @param type
* @param stringResId
* @return
*/
public static boolean isInputedCorrect(Activity context, EditText et, int type, int stringResId) {
try {
if (context != null && stringResId > 0) {
return isInputedCorrect(context, et, type, context.getResources().getString(stringResId));
}
} catch (Exception e) {
Log.e(TAG, "isInputedCorrect try { if (context != null && stringResId > 0) {catch (Exception e) \n" + e.getMessage());
}
return false;
}
/**判断edittext输入文字是否合法
* @param context
* @param et
* @param type
* @return
*/
public static boolean isInputedCorrect(Activity context, EditText et, int type, String errorRemind) {
if (context == null || et == null) {
Log.e(TAG, "isInputedCorrect context == null || et == null >> return false;");
return false;
}
oringinalHintColor = et.getHintTextColors();
String inputed = StringUtil.getTrimedString(et);
switch (type) {
case TYPE_VERIFY:
if (type == TYPE_VERIFY && inputed.length() < 4) {
return showInputedError(context, et, StringUtil.isNotEmpty(errorRemind, true) ? errorRemind : "验证码不能小于4位");
}
break;
case TYPE_PASSWORD:
if (inputed.length() < 6) {
return showInputedError(context, et, StringUtil.isNotEmpty(errorRemind, true) ? errorRemind : "密码不能小于6位");
}
if (StringUtil.isNumberOrAlpha(inputed) == false) {
return showInputedError(context, et, StringUtil.isNotEmpty(errorRemind, true) ? errorRemind : "密码只能含有字母或数字");
}
break;
case TYPE_PHONE:
if (inputed.length() != 11) {
return showInputedError(context, et, StringUtil.isNotEmpty(errorRemind, true) ? errorRemind : "请输入11位手机号");
}
if (StringUtil.isPhone(inputed) == false) {
Toast.makeText(context, "您输入的手机号格式不对哦~", Toast.LENGTH_SHORT).show();
return false;
}
break;
case TYPE_MAIL:
if (StringUtil.isEmail(inputed) == false) {
return showInputedError(context, "您输入的邮箱格式不对哦~");
}
break;
default:
if (StringUtil.isNotEmpty(inputed, true) == false || inputed.equals(StringUtil.getTrimedString(et.getHint()))) {
return showInputedError(context, et, StringUtil.isNotEmpty(errorRemind, true) ? errorRemind : StringUtil.getTrimedString(et));
}
break;
}
et.setHintTextColor(oringinalHintColor);
return true;
}
/**字符不合法提示(toast)
* @param context
* @param resId
* @return
*/
public static boolean showInputedError(Activity context, int resId) {
return showInputedError(context, null, resId);
}
/**字符不合法提示(et == null ? toast : hint)
* @param context
* @param et
* @param resId
* @return
*/
public static boolean showInputedError(Activity context, EditText et, int resId) {
try {
return showInputedError(context, et, context.getResources().getString(resId));
} catch (Exception e) {
Log.e(TAG, "" + e.getMessage());
}
return false;
}
/**字符不合法提示(toast)
* @param context
* @param string
* @return
*/
public static boolean showInputedError(Activity context, String string) {
return showInputedError(context, null, string);
}
/**字符不合法提示(et == null ? toast : hint)
* @param context
* @param et
* @param string
* @return
*/
public static boolean showInputedError(Activity context, EditText et, String string) {
if (context == null || StringUtil.isNotEmpty(string, false) == false) {
Log.e(TAG, "showInputedError context == null || et == null || StringUtil.isNotEmpty(string, false) == false >> return false;");
return false;
}
if (et == null) {
Toast.makeText(context, StringUtil.getTrimedString(string), Toast.LENGTH_SHORT).show();
} else {
et.setText("");
et.setHint(string);
et.setHintTextColor(context.getResources().getColor(R.color.red));
}
return false;
}
//对输入字符判断>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,173 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.HashMap;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseAdapter;
import zuo.biao.library.model.Entry;
import zuo.biao.library.util.ImageLoaderUtil;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
/**通用网格Adapter(url, name)
* *适用于gridView
* @author Lemon
* @use new GridAdapter(...); 具体参考.DemoAdapter
*/
public class GridAdapter extends BaseAdapter<Entry<String, String>> {
private static final String TAG = "GridAdapter";
public GridAdapter(Activity context) {
this(context, R.layout.grid_item);
}
public GridAdapter(Activity context, int layoutRes) {
super(context);
setLayoutRes(layoutRes);
}
private int layoutRes;//item视图资源
public void setLayoutRes(int layoutRes) {
this.layoutRes = layoutRes;
}
private boolean hasName = true;//是否显示名字
public GridAdapter setHasName(boolean hasName) {
this.hasName = hasName;
return this;
}
private boolean hasCheck = false;//是否使用标记功能
public GridAdapter setHasCheck(boolean hasCheck) {
this.hasCheck = hasCheck;
return this;
}
//item标记功能不需要可以删除<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private HashMap<Integer, Boolean> hashMap;//实现选中标记的列表不需要可以删除这里可用List<Integer> checkedList代替
public boolean getItemChecked(int position) {
if (hasCheck == false) {
Log.e(TAG, "<<< !!! hasCheck == false >>>>> ");
return false;
}
return hashMap.get(position);
}
public void setItemChecked(int position, boolean isChecked) {
if (hasCheck == false) {
Log.e(TAG, "<<< !!! hasCheck == false >>>>> ");
return;
}
hashMap.put(position, isChecked);
notifyDataSetChanged();
}
//item标记功能不需要可以删除>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
public int selectedCount = 0;
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = convertView == null ? null : (ViewHolder) convertView.getTag();
if (holder == null) {
convertView = inflater.inflate(layoutRes, parent, false);
holder = new ViewHolder();
holder.ivGridItemHead = (ImageView) convertView.findViewById(R.id.ivGridItemHead);
if (hasName) {
holder.tvGridItemName = (TextView) convertView.findViewById(R.id.tvGridItemName);
}
if (hasCheck) {
holder.ivGridItemCheck = (ImageView) convertView.findViewById(R.id.ivGridItemCheck);
}
convertView.setTag(holder);
}
final Entry<String, String> kvb = getItem(position);
final String name = kvb.getValue();
ImageLoaderUtil.loadImage(holder.ivGridItemHead, kvb.getKey());
if (hasName) {
holder.tvGridItemName.setVisibility(View.VISIBLE);
holder.tvGridItemName.setText(StringUtil.getTrimedString(name));
}
if (hasCheck) {
holder.ivGridItemCheck.setVisibility(View.VISIBLE);
holder.ivGridItemCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setItemChecked(position, !getItemChecked(position));
Log.i(TAG, (getItemChecked(position) ? "" : "取消") + "选择第 " + position + " 个item name=" + name);
}
});
}
return convertView;
}
static class ViewHolder {
public ImageView ivGridItemHead;
public TextView tvGridItemName;
public ImageView ivGridItemCheck;
}
/**刷新列表
* @param list
*/
@Override
public synchronized void refresh(List<Entry<String, String>> list) {
if (list != null && list.size() > 0) {
initList(list);
}
if (hasCheck) {
selectedCount = 0;
for (int i = 0; i < this.list.size(); i++) {
if (getItemChecked(i) == true) {
selectedCount ++;
}
}
}
notifyDataSetChanged();
}
/**标记List<String>中的值是否已被选中
* 不需要可以删除this.list = list;这句
* 要放到constructor这个adapter只有ModleAdapter(Context context, List<Object> list)这一个constructor里去
* @param list
* @return
*/
@SuppressLint("UseSparseArrays")
private void initList(List<Entry<String, String>> list) {
this.list = list;
if (hasCheck) {
hashMap = new HashMap<Integer, Boolean>();
if (list != null) {
for (int i = 0; i < list.size(); i++) {
hashMap.put(i, false);
}
}
}
}
}

View File

@ -1,118 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseAdapter;
import zuo.biao.library.model.Entry;
import zuo.biao.library.util.StringUtil;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.TextView;
/**网格选择器adapter
* @author Lemon
* @use new GridPickerAdapter(...); 具体参考.DemoAdapter
*/
public class GridPickerAdapter extends BaseAdapter<Entry<Integer, String>> {
// private static final String TAG = "GridPickerAdapter";
public static final int TYPE_CONTNET_ENABLE = 0;
public static final int TYPE_CONTNET_UNABLE = 1;
public static final int TYPE_TITLE = 2;
private OnItemSelectedListener onItemSelectedListener;
public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) {
this.onItemSelectedListener = onItemSelectedListener;
}
private int currentPosition;//初始选中位置
private int height;//item高度
public GridPickerAdapter(Activity context, int currentPosition, int height) {
super(context);
this.currentPosition = currentPosition;
this.height = height;
}
public int getCurrentPosition() {
return currentPosition;
}
public String getCurrentItemName() {
return StringUtil.getTrimedString(getItem(getCurrentPosition()).getValue());
}
//getView的常规写法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
private LayoutParams layoutParams;
@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
ViewHolder holder = convertView == null ? null : (ViewHolder) convertView.getTag();
if (holder == null) {
convertView = inflater.inflate(R.layout.grid_picker_item, parent, false);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.tvGridPickerItem);
convertView.setTag(holder);
}
final Entry<Integer, String> data = getItem(position);
final int type = data.getKey();
// if (isEnabled == false && position == currentPosition) {
// currentPosition ++;
// }
holder.tv.setText(StringUtil.getTrimedString(data.getValue()));
holder.tv.setTextColor(resources.getColor(type == TYPE_CONTNET_ENABLE ? R.color.black : R.color.gray_2));
holder.tv.setBackgroundResource(position == currentPosition
? R.drawable.green_rounded_rectangle_normal : R.drawable.null_drawable);
convertView.setBackgroundResource(type == TYPE_TITLE ? R.color.alpha_1 : R.color.alpha_complete);
convertView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (type == TYPE_CONTNET_ENABLE) {
currentPosition = position;
if (onItemSelectedListener != null) {
onItemSelectedListener.onItemSelected(null, v, position, getItemId(position));
}
notifyDataSetChanged();
}
}
});
if (height > 0) {
if (layoutParams == null || layoutParams.height != height) {
layoutParams = convertView.getLayoutParams();
layoutParams.height = height;
}
convertView.setLayoutParams(layoutParams);
}
return convertView;
}
static class ViewHolder {
public TextView tv;
}
//getView的常规写法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

View File

@ -1,363 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import java.util.ArrayList;
import java.util.List;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseView;
import zuo.biao.library.model.Entry;
import zuo.biao.library.model.GridPickerConfig;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.ScreenUtil;
import zuo.biao.library.util.StringUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
/**网格选择器View
* @author Lemon
* @must 调用init方法
* @use 参考 .DemoView
*/
public class GridPickerView extends BaseView<List<Entry<Integer, String>>> {
private static final String TAG = "GridPickerView";
/**tabs切换和gridView的内容切换
*/
public interface OnTabClickListener {
void onTabClick(int tabPosition, TextView tvTab);
}
private OnTabClickListener onTabClickListener;
public void setOnTabClickListener(OnTabClickListener onTabClickListener) {
this.onTabClickListener = onTabClickListener;
}
private OnItemSelectedListener onItemSelectedListener;
public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) {
this.onItemSelectedListener = onItemSelectedListener;
}
private int contentHeight;
public GridPickerView(Activity context, Resources resources) {
super(context, resources);
contentHeight = (int) getDimension(R.dimen.grid_picker_content_height);
}
public LinearLayout llGridPickerViewTabContainer;
public GridView gvGridPickerView;
/**获取View
* @return
*/
@SuppressLint("InflateParams")
@Override
public View createView(LayoutInflater inflater) {
convertView = inflater.inflate(R.layout.grid_picker_view, null);
llGridPickerViewTabContainer = findViewById(R.id.llGridPickerViewTabContainer);
gvGridPickerView = findViewById(R.id.gvGridPickerView);
return convertView;
}
public ArrayList<GridPickerConfig> getConfigList() {
return configList;
}
public ArrayList<String> getSelectedItemList() {
ArrayList<String> list = new ArrayList<String>();
for (GridPickerConfig gpcb : configList) {
list.add(gpcb.getSelectedItemName());
}
return list;
}
public int getTabCount() {
return configList == null ? 0 : configList.size();
}
public boolean isOnFirstTab() {
return getTabCount() <= 0 ? false : getCurrentTabPosition() <= 0;
}
public boolean isOnLastTab() {
return getTabCount() <= 0 ? false : getCurrentTabPosition() >= getTabCount() - 1;
}
private int currentTabPosition;
public int getCurrentTabPosition() {
return currentTabPosition;
}
private String currentTabName;
public String getCurrentTabName() {
return currentTabName;
}
private String currentTabSuffix;
public String getCurrentTabSuffix() {
return currentTabSuffix;
}
public String currentSelectedItemName;
public String getCurrentSelectedItemName() {
return currentSelectedItemName;
}
public int currentSelectedItemPosition;
public int getCurrentSelectedItemPosition() {
return currentSelectedItemPosition;
}
public String getSelectedItemName(int tabPosition) {
return configList.get(tabPosition).getSelectedItemName();
}
public int getSelectedItemPosition(int tabPosition) {
return configList.get(tabPosition).getSelectedItemPostion();
}
public List<Entry<Integer, String>> getList() {
return adapter == null ? null : adapter.list;
}
@Override
public void bindView(List<Entry<Integer, String>> l){/*do nothing,必须init**/}
/**初始化必须使用且只能使用一次
* @param configList
* @param lastList
*/
public final void init(ArrayList<GridPickerConfig> configList, List<Entry<Integer, String>> lastList) {
if (configList == null || configList.size() <= 0) {
Log.e(TAG, "initTabs (configList == null || configList.size() <= 0 " +
">> selectedItemPostionList = new ArrayList<Integer>(); return;");
return;
}
currentTabPosition = configList.size() - 1;
currentTabName = configList.get(currentTabPosition).getTabName();
int tabWidth = configList.size() < 4 ? ScreenUtil.getScreenWidth(context) / configList.size() : 3;
llGridPickerViewTabContainer.removeAllViews();
for (int i = 0; i < configList.size(); i++) {//需要重新设置来保持每个tvTab宽度一致
addTab(i, tabWidth, StringUtil.getTrimedString(configList.get(i)));
}
llGridPickerViewTabContainer.getChildAt(currentTabPosition)
.setBackgroundResource(R.color.alpha_3);
this.configList = configList;
bindView(currentTabPosition, lastList, configList.get(currentTabPosition).getSelectedItemPostion());
}
/**添加tab
* @param tabPosition
* @param tabWidth
* @param name
*/
@SuppressLint("NewApi")
private void addTab(final int tabPosition, int tabWidth, String name) {
if (StringUtil.isNotEmpty(name, true) == false) {
return;
}
name = StringUtil.getTrimedString(name);
final TextView tvTab = new TextView(context);
tvTab.setLayoutParams(new LayoutParams(tabWidth, LayoutParams.MATCH_PARENT));
tvTab.setGravity(Gravity.CENTER);
// tvTab.setPaddingRelative(4, 12, 4, 12);
tvTab.setTextColor(context.getResources().getColor(R.color.black));
tvTab.setBackgroundResource(R.drawable.bg_pressed_common);
tvTab.setTextSize(18);
tvTab.setSingleLine(true);
tvTab.setText(name);
tvTab.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (tabPosition == getCurrentTabPosition()) {
return;
}
if (onTabClickListener != null) {
onTabClickListener.onTabClick(tabPosition, tvTab);
return;
}
//点击就是要切换list这些配置都要改bindView(tabSuffix, tabPosition, tabName, list, numColumns, maxShowRows, itemPosition)
}
});
llGridPickerViewTabContainer.addView(tvTab);
}
private static final int MAX_NUM_TABS = 12;//最大标签数量
private ArrayList<GridPickerConfig> configList;
private GridPickerAdapter adapter;
/**设置并显示内容//可能导致每次都不变
* @param tabPosition
* @param list
*/
public void bindView(final int tabPosition, List<Entry<Integer, String>> list) {
bindView(tabPosition, list, getSelectedItemPosition(tabPosition));
}
/**
* @param tabPosition
* @param list
* @param itemPosition
*/
public void bindView(final int tabPosition, List<Entry<Integer, String>> list, int itemPosition) {//GridView
if (configList == null || configList.size() <= 0) {
Log.e(TAG, "bindView(final int tabPostion, final List<Entry<Integer, String>> list, final int itemPosition) {" +
" >> configList == null || configList.size() <= 0 >> return;");
return;
}
GridPickerConfig gpcb = configList.get(tabPosition);
if (gpcb == null) {
return;
}
if (list == null || list.size() <= 0) {
Log.e(TAG, "bindView(final int tabPostion, final List<Entry<Integer, String>> list, final int itemPosition) {" +
" >> list == null || list.size() <= 0 >> return;");
return;
}
if (tabPosition >= MAX_NUM_TABS) {
Log.e(TAG, "bindView tabPosition >= MAX_NUM_TABS,防止恶意添加标签导致数量过多选择困难甚至崩溃 >> return;");
return;
}
itemPosition = getItemPosition(itemPosition, list);
int numColumns = gpcb.getNumColumns();
if (numColumns <= 0) {
numColumns = 3;
}
int maxShowRows = gpcb.getMaxShowRows();
if (maxShowRows <= 0) {
maxShowRows = 5;
}
//Tabs<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
doOnItemSelected(tabPosition, itemPosition, list.get(itemPosition).getValue());
//Tabs>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//gridView<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
adapter = new GridPickerAdapter(context, itemPosition, contentHeight/maxShowRows);
adapter.refresh(list);
adapter.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
currentSelectedItemName = adapter.getCurrentItemName();
if (isOnLastTab() == false && onItemSelectedListener != null) {
onItemSelectedListener.onItemSelected(parent, view, position, id);
return;
}
doOnItemSelected(tabPosition, position, adapter.getCurrentItemName());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
gvGridPickerView.setNumColumns(numColumns);
gvGridPickerView.setAdapter(adapter);
gvGridPickerView.smoothScrollToPosition(itemPosition);
//gridView>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
private int length;
/**获取itemPosition解决部分不可点击的item被选中的问题
* @param itemPosition
* @param list
* @return
*/
private int getItemPosition(int itemPosition, List<Entry<Integer, String>> list) {
if (itemPosition < 0) {
itemPosition = 0;
} else if (itemPosition >= list.size()) {
itemPosition = list.size() - 1;
}
if (isItemEnabled(list, itemPosition) == false) {
length = Math.max(itemPosition, list.size() - itemPosition);
for (int i = 1; i <= length; i++) {
if (isItemEnabled(list, itemPosition - i)) {
Log.i(TAG, "getItemPosition return " + (itemPosition - i));
return itemPosition - i;
}
if (isItemEnabled(list, itemPosition + i)) {
Log.i(TAG, "getItemPosition return " + (itemPosition + i));
return itemPosition + i;
}
}
}
Log.i(TAG, "getItemPosition return " + itemPosition);
return itemPosition;
}
private boolean isItemEnabled(List<Entry<Integer, String>> list, int itemPosition) {
return list != null && itemPosition >= 0 && itemPosition < list.size()
&& list.get(itemPosition).getKey() == GridPickerAdapter.TYPE_CONTNET_ENABLE;
}
/**在onItemSelected时响应,
* 之后可能会跳转到下一个tab导致 tabPositionWhenItemSelect+=1; selectedItemPosition = 0;
* @param tabPosition
* @param itemPosition
* @param itemName
*/
public void doOnItemSelected(int tabPosition, int itemPosition, String itemName) {
currentTabPosition = tabPosition < getTabCount() ? tabPosition : getTabCount() - 1;
currentSelectedItemPosition = itemPosition;
currentSelectedItemName = StringUtil.getTrimedString(itemName);
configList.set(currentTabPosition, configList.get(currentTabPosition).set(currentSelectedItemName, itemPosition));
for (int i = 0; i < llGridPickerViewTabContainer.getChildCount(); i++) {
((TextView) llGridPickerViewTabContainer.getChildAt(i)).setText("" + configList.get(i).getTabName());
llGridPickerViewTabContainer.getChildAt(i).setBackgroundResource(
i == tabPosition ? R.color.alpha_3 : R.color.alpha_complete);
}
}
}

View File

@ -1,99 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import zuo.biao.library.R;
import zuo.biao.library.util.StringUtil;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
/**通用纵向Item选项dialog
* @author lemon
* @use new ItemDialog(...).show();
*/
public class ItemDialog extends Dialog implements OnItemClickListener {
// private static final String TAG = "ItemDialog";
public interface OnDialogItemClickListener {
/**点击item事件的回调方法
* @param requestCode 传入的用于区分某种情况下的showDialog
* @param position
* @param item
*/
void onDialogItemClick(int requestCode, int position, String item);
}
private Context context;
private String[] items;
private String title;
private int requestCode;
private OnDialogItemClickListener listener;
/**
* 带监听器参数的构造函数
*/
public ItemDialog(Context context, String[] items,
int requestCode, OnDialogItemClickListener listener) {
this(context, items, null, requestCode, listener);
}
public ItemDialog(Context context, String[] items, String title,
int requestCode, OnDialogItemClickListener listener) {
super(context, R.style.MyDialog);
this.context = context;
this.items = items;
this.title = title;
this.requestCode = requestCode;
this.listener = listener;
}
private TextView tvItemDialogTitle;
private ListView lvItemDialog;
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item_dialog);
setCanceledOnTouchOutside(true);
tvItemDialogTitle = (TextView) findViewById(R.id.tvItemDialogTitle);
lvItemDialog = (ListView) findViewById(R.id.lvItemDialog);
tvItemDialogTitle.setVisibility(StringUtil.isNotEmpty(title, true) ? View.VISIBLE : View.GONE);
tvItemDialogTitle.setText("" + StringUtil.getCurrentString());
adapter = new ArrayAdapter<String>(context, R.layout.item_dialog_item, items);
lvItemDialog.setAdapter(adapter);
lvItemDialog.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (listener != null) {
listener.onDialogItemClick(requestCode, position, adapter == null ? null : adapter.getItem(position));
}
dismiss();
}
}

View File

@ -1,69 +0,0 @@
/*Copyright ©2015 TommyLemon(https://github.com/TommyLemon)
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 zuo.biao.library.ui;
import zuo.biao.library.R;
import zuo.biao.library.base.BaseAdapter;
import zuo.biao.library.model.Entry;
import zuo.biao.library.util.StringUtil;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**key-value型(两个都是String类型)Adapter
* @author Lemon
* @use new KeyValueAdapter(...); 具体参考.DemoAdapter
*/
public class KeyValueAdapter extends BaseAdapter<Entry<String, String>> {
private int layoutRes;//布局id
public KeyValueAdapter(Activity context) {
this(context, R.layout.key_value_item);
}
public KeyValueAdapter(Activity context, int layoutRes) {
super(context);
this.layoutRes = layoutRes;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = convertView == null ? null : (ViewHolder) convertView.getTag();
if (holder == null) {
convertView = inflater.inflate(layoutRes, parent, false);
holder = new ViewHolder();
holder.tvKey = (TextView) convertView.findViewById(R.id.tvKeyValueItemKey);
holder.tvValue = (TextView) convertView.findViewById(R.id.tvKeyValueItemValue);
convertView.setTag(holder);
}
final Entry<String, String> data = getItem(position);
holder.tvKey.setText(StringUtil.getTrimedString(data.getKey()));
holder.tvValue.setText(StringUtil.getTrimedString(data.getValue()));
return convertView;
}
static class ViewHolder {
public TextView tvKey;
public TextView tvValue;
}
}

Some files were not shown because too many files have changed in this diff Show More